# HG changeset patch # User Doug Simon # Date 1401789087 -7200 # Node ID 66a9286203a2f14c623366a847597dab8480556c # Parent 83433cf49019ea9de428f4ae88883af58bfa8e25 decoupled Graal runtime initialization and Graal compilation queue initialization diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Tue Jun 03 11:51:27 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; +import static com.oracle.graal.hotspot.InitTimer.*; import java.util.*; @@ -32,7 +32,6 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Tue Jun 03 11:51:27 2014 +0200 @@ -22,13 +22,12 @@ */ package com.oracle.graal.hotspot.ptx; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; +import static com.oracle.graal.hotspot.InitTimer.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java --- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java Tue Jun 03 11:51:27 2014 +0200 @@ -153,7 +153,7 @@ out.println(" case " + len + ":"); out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len); out.println(" if (value[0] == '+') {"); - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);"); + out.println(" set_option_helper(hotSpotOptionsClass, name_handle, Handle(), '?', Handle(), 0L);"); out.println(" }"); out.println(" return true;"); out.println(" }"); @@ -170,14 +170,14 @@ out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), toInternalName(getFieldType(desc))); if (isBoolean) { - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);"); + out.println(" set_option_helper(hotSpotOptionsClass, name_handle, option, value[0], Handle(), 0L);"); } else if (desc.getType() == String.class) { out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);"); + out.println(" set_option_helper(hotSpotOptionsClass, name_handle, option, 's', stringValue, 0L);"); } else { char spec = getPrimitiveSpecChar(desc); out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name_handle, value, CHECK_(true));"); - out.println(" VMToCompiler::setOption(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);"); + out.println(" set_option_helper(hotSpotOptionsClass, name_handle, option, '" + spec + "', Handle(), primitiveValue);"); } out.println(" return true;"); out.println(" }"); diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationQueue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationQueue.java Tue Jun 03 11:51:27 2014 +0200 @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2014, 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 com.oracle.graal.hotspot; + +import static com.oracle.graal.compiler.GraalDebugConfig.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.CompilationQueue.Options.*; +import static com.oracle.graal.hotspot.InitTimer.*; + +import java.lang.reflect.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess; +import com.oracle.graal.debug.*; +import com.oracle.graal.hotspot.CompilationTask.Enqueueing; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.options.*; +import com.oracle.graal.printer.*; + +/** + * A queue for running {@link CompilationTask}s on background compilation thread(s). The singleton + * {@linkplain #queue() instance} is created the first time this class is accessed. + *

+ * Note that this is independent of the HotSpot C++ {@code CompileQueue} used by the + * {@code CompileBroker}. + */ +public class CompilationQueue { + + static { + try (InitTimer t = timer("initialize CompilationQueue")) { + + // Must be first to ensure any options accessed by the rest of the class + // initializer are initialized from the command line. + HotSpotOptions.initialize(); + + // The singleton queue instance is created the first time this class + queue = new CompilationQueue(); + } + } + + public static class Options { + + //@formatter:off + @Option(help = "Print compilation queue activity periodically") + private static final OptionValue PrintQueue = new OptionValue<>(false); + + @Option(help = "Interval in milliseconds at which to print compilation rate periodically. " + + "The compilation statistics are reset after each print out so this option " + + "is incompatible with -XX:+CITime and -XX:+CITimeEach.") + public static final OptionValue PrintCompRate = new OptionValue<>(0); + + @Option(help = "Print bootstrap progress and summary") + static final OptionValue PrintBootstrap = new OptionValue<>(true); + + @Option(help = "Time limit in milliseconds for bootstrap (-1 for no limit)") + static final OptionValue TimedBootstrap = new OptionValue<>(-1); + + @Option(help = "Number of compilation threads to use") + static final StableOptionValue Threads = new StableOptionValue() { + + @Override + public Integer initialValue() { + return Runtime.getRuntime().availableProcessors(); + } + }; + //@formatter:on + + } + + /** + * Prints and resets the Graal compilation rate statistics. + */ + private static native void printAndResetCompRate(); + + /** + * The singleton queue instance. + */ + private static final CompilationQueue queue; + + /** + * Gets the singleton queue instance. + */ + public static final CompilationQueue queue() { + assert queue != null; + return queue; + } + + /** + * The thread pool used to service the queue. + * + * Most access to the thread pool is wrapped to ensure that + * {@link CompilationTask#isWithinEnqueue} is in the proper state. + */ + final ThreadPoolExecutor executor; + + private CompilationQueue() { + CompilerThreadFactory factory = new CompilerThreadFactory("GraalCompilerThread", new DebugConfigAccess() { + public GraalDebugConfig getDebugConfig() { + return Debug.isEnabled() ? DebugEnvironment.initialize(HotSpotGraalRuntime.Options.LogFile.log()) : null; + } + }); + + executor = new ThreadPoolExecutor(Options.Threads.getValue(), Options.Threads.getValue(), 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue(), factory); + + // Create queue status printing thread. + if (Options.PrintQueue.getValue()) { + Thread t = new Thread() { + + @Override + public void run() { + while (true) { + TTY.println(CompilationQueue.this.toString()); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } + }; + t.setDaemon(true); + t.start(); + } + + if (Options.PrintCompRate.getValue() != 0) { + Thread t = new Thread() { + + @Override + public void run() { + while (true) { + printAndResetCompRate(); + try { + Thread.sleep(Options.PrintCompRate.getValue()); + } catch (InterruptedException e) { + } + } + } + }; + t.setDaemon(true); + t.start(); + } + } + + public long getCompletedTaskCount() { + try (Enqueueing enqueueing = new Enqueueing()) { + // Don't allow new enqueues while reading the state of queue. + return executor.getCompletedTaskCount(); + } + } + + public long getTaskCount() { + try (Enqueueing enqueueing = new Enqueueing()) { + // Don't allow new enqueues while reading the state of queue. + return executor.getTaskCount(); + } + } + + public void execute(CompilationTask task) { + // The caller is expected to have set the within enqueue state. + assert CompilationTask.isWithinEnqueue(); + executor.execute(task); + } + + /** + * Shuts down the compilation queue. + * + * Called from VM. + */ + private static void shutdown() throws Exception { + queue.executor.shutdownNow(); + if (Debug.isEnabled() && (Dump.getValue() != null || areMetricsOrTimersEnabled())) { + // Wait up to 2 seconds to flush out all graph dumps and stop metrics/timers + // being updated. + queue.executor.awaitTermination(2, TimeUnit.SECONDS); + } + } + + /** + * This method is the first method compiled during {@linkplain #bootstrap() bootstrapping}. Put + * any code in there that warms up compiler paths that are otherwise not exercised during + * bootstrapping and lead to later deoptimization when application code is compiled. + */ + @Deprecated + private synchronized void compileWarmup() { + // Method is synchronized to exercise the synchronization code in the compiler. + } + + /** + * Adds some compilation tasks to the queue and then loops until the queue has completed all its + * scheduled tasks or the timeout specified by {@link Options#TimedBootstrap} expires. + * + * Called from VM. + */ + private static void bootstrap() throws Throwable { + if (PrintBootstrap.getValue()) { + TTY.print("Bootstrapping Graal"); + TTY.flush(); + } + + long boostrapStartTime = System.currentTimeMillis(); + + boolean firstRun = true; + do { + // Initialize compile queue with a selected set of methods. + Class objectKlass = Object.class; + if (firstRun) { + enqueue(CompilationQueue.class.getDeclaredMethod("compileWarmup")); + enqueue(objectKlass.getDeclaredMethod("equals", Object.class)); + enqueue(objectKlass.getDeclaredMethod("toString")); + firstRun = false; + } else { + for (int i = 0; i < 100; i++) { + enqueue(CompilationQueue.class.getDeclaredMethod("bootstrap")); + } + } + + // Compile until the queue is empty. + int z = 0; + while (true) { + if (queue().getCompletedTaskCount() >= Math.max(3, queue().getTaskCount())) { + break; + } + + Thread.sleep(100); + while (z < queue().getCompletedTaskCount() / 100) { + ++z; + if (PrintBootstrap.getValue()) { + TTY.print("."); + TTY.flush(); + } + } + + // Are we out of time? + final int timedBootstrap = TimedBootstrap.getValue(); + if (timedBootstrap != -1) { + if ((System.currentTimeMillis() - boostrapStartTime) > timedBootstrap) { + break; + } + } + } + } while ((System.currentTimeMillis() - boostrapStartTime) <= TimedBootstrap.getValue()); + + if (ResetDebugValuesAfterBootstrap.getValue()) { + new DebugValuesPrinter().printDebugValues("bootstrap", true); + runtime().getCompilerToVM().resetCompilationStatistics(); + } + phaseTransition("bootstrap"); + + if (PrintBootstrap.getValue()) { + TTY.println(" in %d ms (compiled %d methods)", System.currentTimeMillis() - boostrapStartTime, queue().getCompletedTaskCount()); + } + + System.gc(); + phaseTransition("bootstrap2"); + } + + private static void enqueue(Method m) throws Throwable { + JavaMethod javaMethod = runtime().getHostProviders().getMetaAccess().lookupJavaMethod(m); + assert !((HotSpotResolvedJavaMethod) javaMethod).isAbstract() && !((HotSpotResolvedJavaMethod) javaMethod).isNative() : javaMethod; + CompilationTask.compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, 0L, false); + } + + @Override + public String toString() { + return executor.toString(); + } +} diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Tue Jun 03 11:51:27 2014 +0200 @@ -27,12 +27,15 @@ import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.compiler.common.UnsafeAccess.*; -import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*; +import static com.oracle.graal.hotspot.CompilationQueue.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.InitTimer.*; import static com.oracle.graal.nodes.StructuredGraph.*; import static com.oracle.graal.phases.common.inlining.InliningUtil.*; import java.io.*; import java.lang.management.*; +import java.security.*; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; @@ -47,6 +50,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.hotspot.CompilationQueue.Options; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.events.*; import com.oracle.graal.hotspot.events.EventProvider.CompilationEvent; @@ -60,10 +64,18 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; -import edu.umd.cs.findbugs.annotations.*; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class CompilationTask implements Runnable, Comparable { + static { + try (InitTimer t = timer("initialize CompilationTask")) { + // Must be first to ensure any options accessed by the rest of the class + // initializer are initialized from the command line. + HotSpotOptions.initialize(); + } + } + // Keep static finals in a group with withinEnqueue as the last one. CompilationTask can be // called from within it's own clinit so it needs to be careful about accessing state. Once // withinEnqueue is non-null we assume that CompilationTask is fully initialized. @@ -409,7 +421,7 @@ if (ctask != 0L) { unsafe.putInt(ctask + config.compileTaskNumInlinedBytecodesOffset, processedBytes); } - if ((config.ciTime || config.ciTimeEach || PrintCompRate.getValue() != 0) && installedCode != null) { + if ((config.ciTime || config.ciTimeEach || Options.PrintCompRate.getValue() != 0) && installedCode != null) { long time = CompilationTime.getCurrentValue() - previousCompilationTime; TimeUnit timeUnit = CompilationTime.getTimeUnit(); long timeUnitsPerSecond = timeUnit.convert(1, TimeUnit.SECONDS); @@ -474,4 +486,69 @@ public String toString() { return "Compilation[id=" + id + ", " + MetaUtil.format("%H.%n(%p)", method) + (entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "@" + entryBCI) + "]"; } + + /** + * Entry point for the VM to schedule a compilation for a metaspace Method. + * + * Called from the VM. + */ + @SuppressWarnings("unused") + private static void compileMetaspaceMethod(long metaspaceMethod, final int entryBCI, long ctask, final boolean blocking) { + final HotSpotResolvedJavaMethod method = HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod); + if (ctask != 0L) { + // This is on a VM CompilerThread - no user frames exist + compileMethod(method, entryBCI, ctask, false); + } else { + // We have to use a privileged action here because compilations are + // enqueued from user code which very likely contains unprivileged frames. + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + compileMethod(method, entryBCI, 0L, blocking); + return null; + } + }); + } + } + + /** + * Compiles a method to machine code. + */ + static void compileMethod(final HotSpotResolvedJavaMethod method, final int entryBCI, long ctask, final boolean blocking) { + if (ctask != 0L) { + HotSpotBackend backend = runtime().getHostBackend(); + CompilationTask task = new CompilationTask(null, backend, method, entryBCI, ctask, false); + task.runCompilation(); + return; + } + + if (isWithinEnqueue()) { + // This is required to avoid deadlocking a compiler thread. The issue is that a + // java.util.concurrent.BlockingQueue is used to implement the compilation worker + // queues. If a compiler thread triggers a compilation, then it may be blocked trying + // to add something to its own queue. + return; + } + + // Don't allow blocking compiles from CompilerThreads + boolean block = blocking && !(Thread.currentThread() instanceof CompilerThread); + try (Enqueueing enqueueing = new Enqueueing()) { + if (method.tryToQueueForCompilation()) { + assert method.isQueuedForCompilation(); + + try { + CompilationQueue queue = queue(); + if (!queue.executor.isShutdown()) { + HotSpotBackend backend = runtime().getHostBackend(); + CompilationTask task = new CompilationTask(queue.executor, backend, method, entryBCI, ctask, block); + queue.execute(task); + if (block) { + task.block(); + } + } + } catch (RejectedExecutionException e) { + // The compile queue was already shut down. + } + } + } + } } diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugValuesPrinter.java Tue Jun 03 11:51:27 2014 +0200 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2014, 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 com.oracle.graal.hotspot; + +import static com.oracle.graal.compiler.GraalDebugConfig.*; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; + +/** + * Facility for printing the {@linkplain KeyRegistry#getDebugValues() values} collected across all + * {@link DebugValueMap#getTopLevelMaps() threads}. + */ +public class DebugValuesPrinter { + + public void printDebugValues(String phase, boolean reset) throws GraalInternalError { + if (Debug.isEnabled() && areMetricsOrTimersEnabled()) { + TTY.println(); + if (phase != null) { + TTY.println(""); + } else { + TTY.println(""); + } + List topLevelMaps = DebugValueMap.getTopLevelMaps(); + List debugValues = KeyRegistry.getDebugValues(); + if (debugValues.size() > 0) { + try { + ArrayList sortedValues = new ArrayList<>(debugValues); + Collections.sort(sortedValues); + + String summary = DebugValueSummary.getValue(); + if (summary == null) { + summary = "Complete"; + } + switch (summary) { + case "Name": + printSummary(topLevelMaps, sortedValues); + break; + case "Partial": { + DebugValueMap globalMap = new DebugValueMap("Global"); + for (DebugValueMap map : topLevelMaps) { + flattenChildren(map, globalMap); + } + globalMap.normalize(); + printMap(new DebugValueScope(null, globalMap), sortedValues); + break; + } + case "Complete": { + DebugValueMap globalMap = new DebugValueMap("Global"); + for (DebugValueMap map : topLevelMaps) { + globalMap.addChild(map); + } + globalMap.group(); + globalMap.normalize(); + printMap(new DebugValueScope(null, globalMap), sortedValues); + break; + } + case "Thread": + for (DebugValueMap map : topLevelMaps) { + TTY.println("Showing the results for thread: " + map.getName()); + map.group(); + map.normalize(); + printMap(new DebugValueScope(null, map), sortedValues); + } + break; + default: + throw new GraalInternalError("Unknown summary type: %s", summary); + } + if (reset) { + for (DebugValueMap topLevelMap : topLevelMaps) { + topLevelMap.reset(); + } + } + } catch (Throwable e) { + // Don't want this to change the exit status of the VM + PrintStream err = System.err; + err.println("Error while printing debug values:"); + e.printStackTrace(); + } + } + if (phase != null) { + TTY.println(""); + } else { + TTY.println(""); + } + } + } + + private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) { + globalMap.addChild(map); + for (DebugValueMap child : map.getChildren()) { + flattenChildren(child, globalMap); + } + map.clearChildren(); + } + + private void printSummary(List topLevelMaps, List debugValues) { + DebugValueMap result = new DebugValueMap("Summary"); + for (int i = debugValues.size() - 1; i >= 0; i--) { + DebugValue debugValue = debugValues.get(i); + int index = debugValue.getIndex(); + long total = collectTotal(topLevelMaps, index); + result.setCurrentValue(index, total); + } + printMap(new DebugValueScope(null, result), debugValues); + } + + private long collectTotal(List maps, int index) { + long total = 0; + for (int i = 0; i < maps.size(); i++) { + DebugValueMap map = maps.get(i); + total += map.getCurrentValue(index); + total += collectTotal(map.getChildren(), index); + } + return total; + } + + /** + * Tracks the scope when printing a {@link DebugValueMap}, allowing "empty" scopes to be + * omitted. An empty scope is one in which there are no (nested) non-zero debug values. + */ + static class DebugValueScope { + + final DebugValueScope parent; + final int level; + final DebugValueMap map; + private boolean printed; + + public DebugValueScope(DebugValueScope parent, DebugValueMap map) { + this.parent = parent; + this.map = map; + this.level = parent == null ? 0 : parent.level + 1; + } + + public void print() { + if (!printed) { + printed = true; + if (parent != null) { + parent.print(); + } + printIndent(level); + TTY.println("%s", map.getName()); + } + } + } + + private void printMap(DebugValueScope scope, List debugValues) { + + for (DebugValue value : debugValues) { + long l = scope.map.getCurrentValue(value.getIndex()); + if (l != 0 || !SuppressZeroDebugValues.getValue()) { + scope.print(); + printIndent(scope.level + 1); + TTY.println(value.getName() + "=" + value.toString(l)); + } + } + + for (DebugValueMap child : scope.map.getChildren()) { + printMap(new DebugValueScope(scope, child), debugValues); + } + } + + private static void printIndent(int level) { + for (int i = 0; i < level; ++i) { + TTY.print(" "); + } + TTY.print("|-> "); + } +} diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Jun 03 11:51:27 2014 +0200 @@ -22,12 +22,16 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.compiler.GraalDebugConfig.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.compiler.common.UnsafeAccess.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; +//import static com.oracle.graal.hotspot.CompilationQueue.*; +import static com.oracle.graal.hotspot.CompileTheWorld.Options.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.Options.*; +import static com.oracle.graal.hotspot.InitTimer.*; import static sun.reflect.Reflection.*; +import java.io.*; import java.lang.reflect.*; import java.util.*; @@ -44,11 +48,16 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.CompileTheWorld.Config; import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.debug.*; import com.oracle.graal.hotspot.events.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.java.*; import com.oracle.graal.options.*; +import com.oracle.graal.printer.*; +import com.oracle.graal.replacements.*; import com.oracle.graal.runtime.*; //JaCoCo Exclude @@ -58,66 +67,14 @@ */ public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider, StackIntrospection { - /** - * A facility for timing a step in the initialization sequence for the runtime. This exists - * separate from {@link DebugTimer} as it must be independent from all other Graal code so as to - * not perturb the initialization sequence. - */ - public static class InitTimer implements AutoCloseable { - final String name; - final long start; - - private InitTimer(String name) { - this.name = name; - this.start = System.currentTimeMillis(); - System.out.println("START: " + SPACES.substring(0, timerDepth * 2) + name); - assert Thread.currentThread() == initializingThread; - timerDepth++; - } - - public void close() { - final long end = System.currentTimeMillis(); - timerDepth--; - System.out.println(" DONE: " + SPACES.substring(0, timerDepth * 2) + name + " [" + (end - start) + " ms]"); - } - - public static InitTimer timer(String name) { - return ENABLED ? new InitTimer(name) : null; - } - - public static InitTimer timer(String name, Object suffix) { - return ENABLED ? new InitTimer(name + suffix) : null; - } - - /** - * Specified initialization timing is enabled. This must only be set via a system property - * as the timing facility is used to time initialization of {@link HotSpotOptions}. - */ - private static final boolean ENABLED = Boolean.getBoolean("graal.runtime.TimeInit"); - public static int timerDepth = 0; - public static final String SPACES = " "; - public static final Thread initializingThread = Thread.currentThread(); - } - private static final HotSpotGraalRuntime instance; - /** - * Initializes the native part of the Graal runtime. - */ - private static native void init(Class compilerToVMClass); - static { - try (InitTimer t = timer("initialize natives")) { - init(CompilerToVMImpl.class); - } - try (InitTimer t = timer("initialize HotSpotOptions")) { - // The options must be processed before any code using them... HotSpotOptions.initialize(); } try (InitTimer t = timer("HotSpotGraalRuntime.")) { - // ... including code in the constructor instance = new HotSpotGraalRuntime(); } @@ -156,33 +113,101 @@ // proxied methods. Some of these static initializers (e.g. in // HotSpotMethodData) rely on the static 'instance' field being set // to retrieve configuration details. - VMToCompiler toCompiler = this.vmToCompiler; CompilerToVM toVM = this.compilerToVm; if (CountingProxy.ENABLED) { - toCompiler = CountingProxy.getProxy(VMToCompiler.class, toCompiler); toVM = CountingProxy.getProxy(CompilerToVM.class, toVM); } if (Logger.ENABLED) { - toCompiler = LoggingProxy.getProxy(VMToCompiler.class, toCompiler); toVM = LoggingProxy.getProxy(CompilerToVM.class, toVM); } - this.vmToCompiler = toCompiler; this.compilerToVm = toVM; - this.vmToCompiler.startRuntime(); + TTY.initialize(Options.LogFile.log()); + + if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null) { + if (MethodFilter.getValue() != null) { + TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time and Dump options are all null"); + } + } + + if (Debug.isEnabled()) { + DebugEnvironment.initialize(LogFile.log()); + + String summary = DebugValueSummary.getValue(); + if (summary != null) { + switch (summary) { + case "Name": + case "Partial": + case "Complete": + case "Thread": + break; + default: + throw new GraalInternalError("Unsupported value for DebugSummaryValue: %s", summary); + } + } + } + + final HotSpotProviders hostProviders = hostBackend.getProviders(); + assert VerifyOptionsPhase.checkOptions(hostProviders.getMetaAccess()); + + // Complete initialization of backends + try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { + hostBackend.completeInitialization(); + } + for (HotSpotBackend backend : backends.values()) { + if (backend != hostBackend) { + try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) { + backend.completeInitialization(); + } + } + } + + BenchmarkCounters.initialize(toVM); + + runtimeStartTime = System.nanoTime(); } - // Options must not be directly declared in HotSpotGraalRuntime - see VerifyOptionsPhase - static class Options { + public static class Options { // @formatter:off @Option(help = "The runtime configuration to use") static final OptionValue GraalRuntime = new OptionValue<>(""); + + @Option(help = "File to which logging is sent") + public static final LogFileOption LogFile = new LogFileOption(); // @formatter:on } + public static class LogFileOption extends OptionValue { + public LogFileOption() { + super(null); + } + + private volatile PrintStream log; + + public PrintStream log() { + if (log == null) { + if (getValue() != null) { + synchronized (this) { + if (log == null) { + try { + final boolean enableAutoflush = true; + log = new PrintStream(new FileOutputStream(LogFile.getValue()), enableAutoflush); + } catch (FileNotFoundException e) { + throw new RuntimeException("couldn't open log file: " + LogFile.getValue(), e); + } + } + } + } else { + log = System.out; + } + } + return log; + } + } + private static HotSpotBackendFactory findFactory(String architecture) { HotSpotBackendFactory basic = null; HotSpotBackendFactory selected = null; @@ -265,7 +290,6 @@ } protected/* final */CompilerToVM compilerToVm; - protected/* final */VMToCompiler vmToCompiler; protected final HotSpotVMConfig config; private final HotSpotBackend hostBackend; @@ -291,10 +315,7 @@ private HotSpotGraalRuntime() { CompilerToVM toVM = new CompilerToVMImpl(); - VMToCompiler toCompiler = new VMToCompilerImpl(this); - compilerToVm = toVM; - vmToCompiler = toCompiler; try (InitTimer t = timer("HotSpotVMConfig")) { config = new HotSpotVMConfig(compilerToVm); } @@ -401,10 +422,6 @@ return compilerToVm; } - public VMToCompiler getVMToCompiler() { - return vmToCompiler; - } - /** * Converts a name to a Java type. * @@ -601,4 +618,45 @@ return result; } } + + private long runtimeStartTime; + + /** + * Take action related to entering a new execution phase. + * + * @param phase the execution phase being entered + */ + static void phaseTransition(String phase) { + CompilationStatistics.clear(phase); + } + + /** + * Called from the VM. + */ + @SuppressWarnings("unused") + private void compileTheWorld() throws Throwable { + int iterations = CompileTheWorld.Options.CompileTheWorldIterations.getValue(); + for (int i = 0; i < iterations; i++) { + getCompilerToVM().resetCompilationStatistics(); + TTY.println("CompileTheWorld : iteration " + i); + CompileTheWorld ctw = new CompileTheWorld(CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), + CompileTheWorldStopAt.getValue(), CompileTheWorldVerbose.getValue()); + ctw.compile(); + } + System.exit(0); + } + + /** + * Shuts down the runtime. + * + * Called from the VM. + */ + @SuppressWarnings("unused") + private void shutdown() throws Exception { + new DebugValuesPrinter().printDebugValues(ResetDebugValuesAfterBootstrap.getValue() ? "application" : null, false); + phaseTransition("final"); + + SnippetCounter.printGroups(TTY.out().out()); + BenchmarkCounters.shutdown(getCompilerToVM(), runtimeStartTime); + } } diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java Tue Jun 03 11:51:27 2014 +0200 @@ -23,14 +23,13 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; +import static com.oracle.graal.hotspot.InitTimer.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.spi.*; diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Tue Jun 03 11:51:27 2014 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.GraalDebugConfig.*; +import static com.oracle.graal.hotspot.CompilationQueue.Options.*; import static com.oracle.graal.hotspot.HotSpotOptionsLoader.*; -import static com.oracle.graal.hotspot.bridge.VMToCompilerImpl.*; import static java.lang.Double.*; import java.lang.reflect.*; @@ -37,8 +37,8 @@ import com.oracle.graal.phases.common.inlining.*; /** - * Called from {@code graalCompiler.cpp} to set Graal options from the HotSpot command line. Such - * options are (currently) distinguished by a {@code "-G:"} prefix. + * Sets Graal options from the HotSpot command line. Such options are distinguished by a + * {@code "-G:"} prefix. */ public class HotSpotOptions { @@ -52,6 +52,9 @@ static { boolean timeCompilations = parseVMOptions(); if (timeCompilations || PrintCompRate.getValue() != 0) { + if (timeCompilations && PrintCompRate.getValue() != 0) { + throw new GraalInternalError("PrintCompRate is incompatible with CITime and CITimeEach"); + } unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes"); unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime"); } diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/InitTimer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/InitTimer.java Tue Jun 03 11:51:27 2014 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, 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 com.oracle.graal.hotspot; + +import com.oracle.graal.debug.*; + +import edu.umd.cs.findbugs.annotations.*; + +/** + * A facility for timing a step in the runtime or compilation queue initialization sequence. This + * exists separate from {@link DebugTimer} as it must be independent from all other Graal code so as + * to not perturb the initialization sequence. + */ +public class InitTimer implements AutoCloseable { + final String name; + final long start; + + private InitTimer(String name) { + this.name = name; + this.start = System.currentTimeMillis(); + System.out.println("START: " + SPACES.substring(0, timerDepth * 2) + name); + assert Thread.currentThread() == initializingThread : Thread.currentThread() + " != " + initializingThread; + timerDepth++; + } + + @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "only the initializing thread accesses this field") + public void close() { + final long end = System.currentTimeMillis(); + timerDepth--; + System.out.println(" DONE: " + SPACES.substring(0, timerDepth * 2) + name + " [" + (end - start) + " ms]"); + } + + public static InitTimer timer(String name) { + return ENABLED ? new InitTimer(name) : null; + } + + public static InitTimer timer(String name, Object suffix) { + return ENABLED ? new InitTimer(name + suffix) : null; + } + + /** + * Specifies if initialization timing is enabled. This can only be set via a system property as + * the timing facility is used to time initialization of {@link HotSpotOptions}. + */ + private static final boolean ENABLED = Boolean.getBoolean("graal.runtime.TimeInit"); + + public static int timerDepth = 0; + public static final String SPACES = " "; + + /** + * Used to assert the invariant that all initialization happens on the same thread. + */ + public static final Thread initializingThread; + static { + if (ENABLED) { + initializingThread = Thread.currentThread(); + System.out.println("INITIALIZING THREAD: " + initializingThread); + } else { + initializingThread = null; + } + } +} diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Jun 03 11:51:27 2014 +0200 @@ -241,8 +241,6 @@ */ void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode); - void printCompilationStatistics(boolean perCompiler, boolean aggregate); - void resetCompilationStatistics(); void initializeConfiguration(HotSpotVMConfig config); @@ -334,7 +332,7 @@ /** * Gets the value of a metaspace {@code Symbol} as a String. - * + * * @param metaspaceSymbol */ String getSymbol(long metaspaceSymbol); diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Jun 03 11:51:27 2014 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.hotspot.bridge; +import static com.oracle.graal.hotspot.InitTimer.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; @@ -32,6 +34,17 @@ */ public class CompilerToVMImpl implements CompilerToVM { + /** + * Initializes the native part of the Graal runtime. + */ + private static native void init(); + + static { + try (InitTimer t = timer("CompilerToVMImpl.init")) { + init(); + } + } + private native int installCode0(HotSpotCompiledCode compiledCode, InstalledCode code, SpeculationLog speculationLog); @Override @@ -157,8 +170,6 @@ public synchronized native void notifyCompilationStatistics(int id, HotSpotResolvedJavaMethod method, boolean osr, int processedBytecodes, long time, long timeUnitsPerSecond, InstalledCode installedCode); - public synchronized native void printCompilationStatistics(boolean perCompiler, boolean aggregate); - public native void resetCompilationStatistics(); public native long[] collectCounters(); diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java Tue Jun 03 11:01:58 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2011, 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 com.oracle.graal.hotspot.bridge; - -import java.io.*; - -/** - * Calls from HotSpot into Java. - */ -public interface VMToCompiler { - - void startRuntime(); - - void startCompiler(boolean bootstrapEnabled) throws Throwable; - - void bootstrap() throws Throwable; - - /** - * Compiles a method to machine code. This method is called from the VM - * (VMToCompiler::compileMethod). - * - * @param ctask the CompileTask pointer if this is a request from a HotSpot compiler thread - */ - void compileMethod(long metaspaceMethod, int entryBCI, long ctask, boolean blocking); - - void shutdownCompiler() throws Exception; - - void shutdownRuntime() throws Throwable; - - void compileTheWorld() throws Throwable; - - PrintStream log(); -} diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Jun 03 11:01:58 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,627 +0,0 @@ -/* - * Copyright (c) 2011, 2012, 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 com.oracle.graal.hotspot.bridge; - -import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.hotspot.CompileTheWorld.Options.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer.*; - -import java.io.*; -import java.lang.reflect.*; -import java.security.*; -import java.util.*; -import java.util.concurrent.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.debug.internal.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.CompilationTask.Enqueueing; -import com.oracle.graal.hotspot.CompileTheWorld.Config; -import com.oracle.graal.hotspot.HotSpotGraalRuntime.InitTimer; -import com.oracle.graal.hotspot.debug.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.options.*; -import com.oracle.graal.printer.*; -import com.oracle.graal.replacements.*; - -/** - * Exits from the HotSpot VM into Java code. - */ -public class VMToCompilerImpl implements VMToCompiler { - - //@formatter:off - @Option(help = "File to which compiler logging is sent") - private static final OptionValue LogFile = new OptionValue<>(null); - - @Option(help = "Print compilation queue activity periodically") - private static final OptionValue PrintQueue = new OptionValue<>(false); - - @Option(help = "Interval in milliseconds at which to print compilation rate periodically. " + - "The compilation statistics are reset after each print out so this option " + - "is incompatible with -XX:+CITime and -XX:+CITimeEach.") - public static final OptionValue PrintCompRate = new OptionValue<>(0); - - @Option(help = "Print bootstrap progress and summary") - private static final OptionValue PrintBootstrap = new OptionValue<>(true); - - @Option(help = "Time limit in milliseconds for bootstrap (-1 for no limit)") - private static final OptionValue TimedBootstrap = new OptionValue<>(-1); - - @Option(help = "Number of compilation threads to use") - private static final StableOptionValue Threads = new StableOptionValue() { - - @Override - public Integer initialValue() { - return Runtime.getRuntime().availableProcessors(); - } - }; - - //@formatter:on - - private final HotSpotGraalRuntime runtime; - - private Queue compileQueue; - - /** - * Wrap access to the thread pool to ensure that {@link CompilationTask#isWithinEnqueue} state - * is in the proper state. - */ - static class Queue { - private final ThreadPoolExecutor executor; - - Queue(CompilerThreadFactory factory) { - executor = new ThreadPoolExecutor(Threads.getValue(), Threads.getValue(), 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue(), factory); - } - - public long getCompletedTaskCount() { - try (Enqueueing enqueueing = new Enqueueing()) { - // Don't allow new enqueues while reading the state of queue. - return executor.getCompletedTaskCount(); - } - } - - public long getTaskCount() { - try (Enqueueing enqueueing = new Enqueueing()) { - // Don't allow new enqueues while reading the state of queue. - return executor.getTaskCount(); - } - } - - public void execute(CompilationTask task) { - // The caller is expected to have set the within enqueue state. - assert CompilationTask.isWithinEnqueue(); - executor.execute(task); - } - - /** - * @see ExecutorService#isShutdown() - */ - public boolean isShutdown() { - return executor.isShutdown(); - } - - public void shutdown() throws InterruptedException { - assert CompilationTask.isWithinEnqueue(); - executor.shutdownNow(); - if (Debug.isEnabled() && (Dump.getValue() != null || areMetricsOrTimersEnabled())) { - // Wait up to 2 seconds to flush out all graph dumps and stop metrics/timers - // being updated. - executor.awaitTermination(2, TimeUnit.SECONDS); - } - } - - @Override - public String toString() { - return executor.toString(); - } - } - - private volatile boolean bootstrapRunning; - - private PrintStream log = System.out; - - private long runtimeStartTime; - - public VMToCompilerImpl(HotSpotGraalRuntime runtime) { - this.runtime = runtime; - } - - public void startRuntime() { - - if (LogFile.getValue() != null) { - try { - final boolean enableAutoflush = true; - log = new PrintStream(new FileOutputStream(LogFile.getValue()), enableAutoflush); - } catch (FileNotFoundException e) { - throw new RuntimeException("couldn't open log file: " + LogFile.getValue(), e); - } - } - - TTY.initialize(log); - - if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null) { - if (MethodFilter.getValue() != null) { - TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time and Dump options are all null"); - } - } - - if (Debug.isEnabled()) { - DebugEnvironment.initialize(log); - - String summary = DebugValueSummary.getValue(); - if (summary != null) { - switch (summary) { - case "Name": - case "Partial": - case "Complete": - case "Thread": - break; - default: - throw new GraalInternalError("Unsupported value for DebugSummaryValue: %s", summary); - } - } - } - - HotSpotBackend hostBackend = runtime.getHostBackend(); - final HotSpotProviders hostProviders = hostBackend.getProviders(); - assert VerifyOptionsPhase.checkOptions(hostProviders.getMetaAccess()); - - // Complete initialization of backends - try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { - hostBackend.completeInitialization(); - } - for (HotSpotBackend backend : runtime.getBackends().values()) { - if (backend != hostBackend) { - try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) { - backend.completeInitialization(); - } - } - } - - BenchmarkCounters.initialize(runtime.getCompilerToVM()); - - runtimeStartTime = System.nanoTime(); - } - - public void startCompiler(boolean bootstrapEnabled) throws Throwable { - try (InitTimer timer = timer("startCompiler")) { - startCompiler0(bootstrapEnabled); - } - } - - private void startCompiler0(boolean bootstrapEnabled) throws Throwable { - - bootstrapRunning = bootstrapEnabled; - - if (runtime.getConfig().useGraalCompilationQueue) { - - // Create compilation queue. - CompilerThreadFactory factory = new CompilerThreadFactory("GraalCompilerThread", new DebugConfigAccess() { - public GraalDebugConfig getDebugConfig() { - return Debug.isEnabled() ? DebugEnvironment.initialize(log) : null; - } - }); - compileQueue = new Queue(factory); - - // Create queue status printing thread. - if (PrintQueue.getValue()) { - Thread t = new Thread() { - - @Override - public void run() { - while (true) { - TTY.println(compileQueue.toString()); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } - } - } - }; - t.setDaemon(true); - t.start(); - } - - if (PrintCompRate.getValue() != 0) { - if (runtime.getConfig().ciTime || runtime.getConfig().ciTimeEach) { - throw new GraalInternalError("PrintCompRate is incompatible with CITime and CITimeEach"); - } - Thread t = new Thread() { - - @Override - public void run() { - while (true) { - runtime.getCompilerToVM().printCompilationStatistics(true, false); - runtime.getCompilerToVM().resetCompilationStatistics(); - try { - Thread.sleep(PrintCompRate.getValue()); - } catch (InterruptedException e) { - } - } - } - }; - t.setDaemon(true); - t.start(); - } - } - } - - /** - * Take action related to entering a new execution phase. - * - * @param phase the execution phase being entered - */ - protected void phaseTransition(String phase) { - CompilationStatistics.clear(phase); - } - - /** - * This method is the first method compiled during bootstrapping. Put any code in there that - * warms up compiler paths that are otherwise not exercised during bootstrapping and lead to - * later deoptimization when application code is compiled. - */ - @SuppressWarnings("unused") - @Deprecated - private synchronized void compileWarmup() { - // Method is synchronized to exercise the synchronization code in the compiler. - } - - public void bootstrap() throws Throwable { - if (PrintBootstrap.getValue()) { - TTY.print("Bootstrapping Graal"); - TTY.flush(); - } - - long boostrapStartTime = System.currentTimeMillis(); - - boolean firstRun = true; - do { - // Initialize compile queue with a selected set of methods. - Class objectKlass = Object.class; - if (firstRun) { - enqueue(getClass().getDeclaredMethod("compileWarmup")); - enqueue(objectKlass.getDeclaredMethod("equals", Object.class)); - enqueue(objectKlass.getDeclaredMethod("toString")); - firstRun = false; - } else { - for (int i = 0; i < 100; i++) { - enqueue(getClass().getDeclaredMethod("bootstrap")); - } - } - - // Compile until the queue is empty. - int z = 0; - while (true) { - if (compileQueue.getCompletedTaskCount() >= Math.max(3, compileQueue.getTaskCount())) { - break; - } - - Thread.sleep(100); - while (z < compileQueue.getCompletedTaskCount() / 100) { - ++z; - if (PrintBootstrap.getValue()) { - TTY.print("."); - TTY.flush(); - } - } - - // Are we out of time? - final int timedBootstrap = TimedBootstrap.getValue(); - if (timedBootstrap != -1) { - if ((System.currentTimeMillis() - boostrapStartTime) > timedBootstrap) { - break; - } - } - } - } while ((System.currentTimeMillis() - boostrapStartTime) <= TimedBootstrap.getValue()); - - if (ResetDebugValuesAfterBootstrap.getValue()) { - printDebugValues("bootstrap", true); - runtime.getCompilerToVM().resetCompilationStatistics(); - } - phaseTransition("bootstrap"); - - bootstrapRunning = false; - - if (PrintBootstrap.getValue()) { - TTY.println(" in %d ms (compiled %d methods)", System.currentTimeMillis() - boostrapStartTime, compileQueue.getCompletedTaskCount()); - } - - System.gc(); - phaseTransition("bootstrap2"); - } - - public void compileTheWorld() throws Throwable { - int iterations = CompileTheWorld.Options.CompileTheWorldIterations.getValue(); - for (int i = 0; i < iterations; i++) { - runtime.getCompilerToVM().resetCompilationStatistics(); - TTY.println("CompileTheWorld : iteration " + i); - CompileTheWorld ctw = new CompileTheWorld(CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), - CompileTheWorldStopAt.getValue(), CompileTheWorldVerbose.getValue()); - ctw.compile(); - } - System.exit(0); - } - - private void enqueue(Method m) throws Throwable { - JavaMethod javaMethod = runtime.getHostProviders().getMetaAccess().lookupJavaMethod(m); - assert !((HotSpotResolvedJavaMethod) javaMethod).isAbstract() && !((HotSpotResolvedJavaMethod) javaMethod).isNative() : javaMethod; - compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, 0L, false); - } - - public void shutdownCompiler() throws Exception { - if (runtime.getConfig().useGraalCompilationQueue) { - try (Enqueueing enqueueing = new Enqueueing()) { - // We have to use a privileged action here because shutting down the compiler might - // be called from user code which very likely contains unprivileged frames. - AccessController.doPrivileged(new PrivilegedExceptionAction() { - public Void run() throws Exception { - if (compileQueue != null) { - compileQueue.shutdown(); - } - return null; - } - }); - } - } - } - - public void shutdownRuntime() throws Exception { - printDebugValues(ResetDebugValuesAfterBootstrap.getValue() ? "application" : null, false); - phaseTransition("final"); - - SnippetCounter.printGroups(TTY.out().out()); - BenchmarkCounters.shutdown(runtime.getCompilerToVM(), runtimeStartTime); - } - - private void printDebugValues(String phase, boolean reset) throws GraalInternalError { - if (Debug.isEnabled() && areMetricsOrTimersEnabled()) { - TTY.println(); - if (phase != null) { - TTY.println(""); - } else { - TTY.println(""); - } - List topLevelMaps = DebugValueMap.getTopLevelMaps(); - List debugValues = KeyRegistry.getDebugValues(); - if (debugValues.size() > 0) { - try { - ArrayList sortedValues = new ArrayList<>(debugValues); - Collections.sort(sortedValues); - - String summary = DebugValueSummary.getValue(); - if (summary == null) { - summary = "Complete"; - } - switch (summary) { - case "Name": - printSummary(topLevelMaps, sortedValues); - break; - case "Partial": { - DebugValueMap globalMap = new DebugValueMap("Global"); - for (DebugValueMap map : topLevelMaps) { - flattenChildren(map, globalMap); - } - globalMap.normalize(); - printMap(new DebugValueScope(null, globalMap), sortedValues); - break; - } - case "Complete": { - DebugValueMap globalMap = new DebugValueMap("Global"); - for (DebugValueMap map : topLevelMaps) { - globalMap.addChild(map); - } - globalMap.group(); - globalMap.normalize(); - printMap(new DebugValueScope(null, globalMap), sortedValues); - break; - } - case "Thread": - for (DebugValueMap map : topLevelMaps) { - TTY.println("Showing the results for thread: " + map.getName()); - map.group(); - map.normalize(); - printMap(new DebugValueScope(null, map), sortedValues); - } - break; - default: - throw new GraalInternalError("Unknown summary type: %s", summary); - } - if (reset) { - for (DebugValueMap topLevelMap : topLevelMaps) { - topLevelMap.reset(); - } - } - } catch (Throwable e) { - // Don't want this to change the exit status of the VM - PrintStream err = System.err; - err.println("Error while printing debug values:"); - e.printStackTrace(); - } - } - if (phase != null) { - TTY.println(""); - } else { - TTY.println(""); - } - } - } - - private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) { - globalMap.addChild(map); - for (DebugValueMap child : map.getChildren()) { - flattenChildren(child, globalMap); - } - map.clearChildren(); - } - - private static void printSummary(List topLevelMaps, List debugValues) { - DebugValueMap result = new DebugValueMap("Summary"); - for (int i = debugValues.size() - 1; i >= 0; i--) { - DebugValue debugValue = debugValues.get(i); - int index = debugValue.getIndex(); - long total = collectTotal(topLevelMaps, index); - result.setCurrentValue(index, total); - } - printMap(new DebugValueScope(null, result), debugValues); - } - - private static long collectTotal(List maps, int index) { - long total = 0; - for (int i = 0; i < maps.size(); i++) { - DebugValueMap map = maps.get(i); - total += map.getCurrentValue(index); - total += collectTotal(map.getChildren(), index); - } - return total; - } - - /** - * Tracks the scope when printing a {@link DebugValueMap}, allowing "empty" scopes to be - * omitted. An empty scope is one in which there are no (nested) non-zero debug values. - */ - static class DebugValueScope { - - final DebugValueScope parent; - final int level; - final DebugValueMap map; - private boolean printed; - - public DebugValueScope(DebugValueScope parent, DebugValueMap map) { - this.parent = parent; - this.map = map; - this.level = parent == null ? 0 : parent.level + 1; - } - - public void print() { - if (!printed) { - printed = true; - if (parent != null) { - parent.print(); - } - printIndent(level); - TTY.println("%s", map.getName()); - } - } - } - - private static void printMap(DebugValueScope scope, List debugValues) { - - for (DebugValue value : debugValues) { - long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue()) { - scope.print(); - printIndent(scope.level + 1); - TTY.println(value.getName() + "=" + value.toString(l)); - } - } - - for (DebugValueMap child : scope.map.getChildren()) { - printMap(new DebugValueScope(scope, child), debugValues); - } - } - - private static void printIndent(int level) { - for (int i = 0; i < level; ++i) { - TTY.print(" "); - } - TTY.print("|-> "); - } - - @Override - public void compileMethod(long metaspaceMethod, final int entryBCI, long ctask, final boolean blocking) { - final HotSpotResolvedJavaMethod method = HotSpotResolvedJavaMethod.fromMetaspace(metaspaceMethod); - if (ctask != 0L) { - // This is on a VM CompilerThread - no user frames exist - compileMethod(method, entryBCI, ctask, false); - } else { - // We have to use a privileged action here because compilations are - // enqueued from user code which very likely contains unprivileged frames. - AccessController.doPrivileged(new PrivilegedAction() { - public Void run() { - compileMethod(method, entryBCI, 0L, blocking); - return null; - } - }); - } - } - - /** - * Compiles a method to machine code. - */ - void compileMethod(final HotSpotResolvedJavaMethod method, final int entryBCI, long ctask, final boolean blocking) { - if (ctask != 0L) { - HotSpotBackend backend = runtime.getHostBackend(); - CompilationTask task = new CompilationTask(null, backend, method, entryBCI, ctask, false); - task.runCompilation(); - return; - } - - boolean osrCompilation = entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI; - if (osrCompilation && bootstrapRunning) { - // no OSR compilations during bootstrap - the compiler is just too slow at this point, - // and we know that there are no endless loops - return; - } - - if (CompilationTask.isWithinEnqueue()) { - // This is required to avoid deadlocking a compiler thread. The issue is that a - // java.util.concurrent.BlockingQueue is used to implement the compilation worker - // queues. If a compiler thread triggers a compilation, then it may be blocked trying - // to add something to its own queue. - return; - } - - // Don't allow blocking compiles from CompilerThreads - boolean block = blocking && !(Thread.currentThread() instanceof CompilerThread); - try (Enqueueing enqueueing = new Enqueueing()) { - if (method.tryToQueueForCompilation()) { - assert method.isQueuedForCompilation(); - - try { - if (!compileQueue.executor.isShutdown()) { - HotSpotBackend backend = runtime.getHostBackend(); - CompilationTask task = new CompilationTask(compileQueue.executor, backend, method, entryBCI, ctask, block); - compileQueue.execute(task); - if (block) { - task.block(); - } - } - } catch (RejectedExecutionException e) { - // The compile queue was already shut down. - } - } - } - } - - @Override - public PrintStream log() { - return log; - } -} diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/logging/Logger.java Tue Jun 03 11:51:27 2014 +0200 @@ -27,9 +27,10 @@ import java.util.*; import com.oracle.graal.debug.*; +import com.oracle.graal.hotspot.bridge.*; /** - * Scoped logging class used to display the call hierarchy of VMToCompiler/CompilerToVM calls. + * Scoped logging class used to display the call hierarchy of {@link CompilerToVM} calls. */ public class Logger { diff -r 83433cf49019 -r 66a9286203a2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Tue Jun 03 11:01:58 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Tue Jun 03 11:51:27 2014 +0200 @@ -42,7 +42,7 @@ */ public FloatEqualsNode(ValueNode x, ValueNode y) { super(x, y); - assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp; + assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp : x.stamp() + " " + y.stamp(); assert x.stamp().isCompatible(y.stamp()); } diff -r 83433cf49019 -r 66a9286203a2 src/gpu/hsail/vm/gpu_hsail.cpp --- a/src/gpu/hsail/vm/gpu_hsail.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -39,7 +39,6 @@ #include "hsailJavaCallArguments.hpp" #include "code/pcDesc.hpp" #include "code/scopeDesc.hpp" -#include "graal/graalVMToCompiler.hpp" #include "gpu_hsail_Frame.hpp" // Entry to GPU native method implementation that transitions current thread to '_thread_in_vm'. diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Tue Jun 03 11:51:27 2014 +0200 @@ -209,6 +209,7 @@ do_klass(HotSpotObjectConstant_klass, com_oracle_graal_hotspot_meta_HotSpotObjectConstant, Opt) \ do_klass(HotSpotMetaspaceConstant_klass, com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant, Opt) \ do_klass(HotSpotStackFrameReference_klass, com_oracle_graal_hotspot_HotSpotStackFrameReference, Opt) \ + do_klass(CompilationTask_klass, com_oracle_graal_hotspot_CompilationTask, Opt) \ /* graal.api.code */ \ do_klass(Assumptions_klass, com_oracle_graal_api_code_Assumptions, Opt) \ do_klass(Assumptions_ConcreteMethod_klass, com_oracle_graal_api_code_Assumptions_ConcreteMethod, Opt) \ diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Jun 03 11:51:27 2014 +0200 @@ -303,7 +303,6 @@ template(com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub, "com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub") \ template(com_oracle_graal_hotspot_HotSpotForeignCallLinkage, "com/oracle/graal/hotspot/HotSpotForeignCallLinkage") \ template(com_oracle_graal_hotspot_HotSpotReferenceMap, "com/oracle/graal/hotspot/HotSpotReferenceMap") \ - template(com_oracle_graal_hotspot_bridge_VMToCompiler, "com/oracle/graal/hotspot/bridge/VMToCompiler") \ template(com_oracle_graal_hotspot_bridge_CompilerToVMImpl, "com/oracle/graal/hotspot/bridge/CompilerToVMImpl") \ template(com_oracle_graal_hotspot_data_DataSection, "com/oracle/graal/hotspot/data/DataSection") \ template(com_oracle_graal_hotspot_data_DataSectionReference, "com/oracle/graal/hotspot/data/DataSectionReference") \ @@ -318,6 +317,7 @@ template(com_oracle_graal_hotspot_meta_HotSpotObjectConstant, "com/oracle/graal/hotspot/meta/HotSpotObjectConstant") \ template(com_oracle_graal_hotspot_meta_HotSpotMetaspaceConstant, "com/oracle/graal/hotspot/meta/HotSpotMetaspaceConstant") \ template(com_oracle_graal_hotspot_HotSpotStackFrameReference, "com/oracle/graal/hotspot/HotSpotStackFrameReference") \ + template(com_oracle_graal_hotspot_CompilationTask, "com/oracle/graal/hotspot/CompilationTask") \ /* graal.api.meta */ \ template(com_oracle_graal_api_meta_Constant, "com/oracle/graal/api/meta/Constant") \ template(com_oracle_graal_api_meta_PrimitiveConstant, "com/oracle/graal/api/meta/PrimitiveConstant") \ @@ -356,13 +356,9 @@ /* graal.gpu */ \ template(com_oracle_graal_gpu_ExternalCompilationResult, "com/oracle/graal/gpu/ExternalCompilationResult") \ /* graal method and field names */ \ - template(compileMethod_name, "compileMethod") \ - template(compileMethod_signature, "(JIJZ)V") \ - template(setOption_name, "setOption") \ - template(setOption_signature, "(Ljava/lang/String;)Z") \ - template(getVMToCompiler_name, "getVMToCompiler") \ - template(getVMToCompiler_signature, "()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;") \ - \ + template(compileMetaspaceMethod_name, "compileMetaspaceMethod") \ + template(compileMetaspaceMethod_signature, "(JIJZ)V") \ + \ /* common method and field names */ \ template(object_initializer_name, "") \ template(class_initializer_name, "") \ diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/compiler/abstractCompiler.hpp --- a/src/share/vm/compiler/abstractCompiler.hpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/compiler/abstractCompiler.hpp Tue Jun 03 11:51:27 2014 +0200 @@ -46,6 +46,9 @@ _bytes += bytes; _count++; } + void reset() { + _time.reset(); + } }; public: diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/compiler/compileBroker.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -1152,11 +1152,11 @@ assert(TieredCompilation || comp_level == CompLevel_full_optimization, "incorrect compile level"); assert(CompLevel_full_optimization == CompLevel_highest_tier, "incorrect level definition"); if (comp_level == CompLevel_full_optimization) { - if (!JavaThread::current()->is_graal_compiling()) { + JavaThread* javaThread = JavaThread::current(); + if (javaThread->can_schedule_graal_compilation()) { bool blockingCompilation = is_compile_blocking(method, osr_bci); + NoGraalCompilationScheduling ngcs(javaThread); GraalCompiler::instance()->compile_method(method, osr_bci, NULL, blockingCompilation); - } else { - // Can't enqueue this request because there would be no one to service it, so simply return. } return; } @@ -2358,6 +2358,17 @@ } } +#ifdef GRAAL +void CompileBroker::print_times(AbstractCompiler* comp) { + CompilerStatistics* stats = comp->stats(); + tty->print_cr(" %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}", + comp->name(), stats->bytes_per_second(), + stats->_standard._time.seconds(), stats->_standard._bytes, stats->_standard._count, + stats->_osr._time.seconds(), stats->_osr._bytes, stats->_osr._count, + stats->_nmethods_size, stats->_nmethods_code_size); +} +#endif + void CompileBroker::print_times(bool per_compiler, bool aggregate) { #ifdef GRAAL elapsedTimer standard_compilation; @@ -2400,11 +2411,7 @@ nmethods_code_size += stats->_nmethods_code_size; if (per_compiler) { - tty->print_cr(" %s {speed: %d bytes/s; standard: %6.3f s, %d bytes, %d methods; osr: %6.3f s, %d bytes, %d methods; nmethods_size: %d bytes; nmethods_code_size: %d bytes}", - comp->name(), stats->bytes_per_second(), - stats->_standard._time.seconds(), stats->_standard._bytes, stats->_standard._count, - stats->_osr._time.seconds(), stats->_osr._bytes, stats->_osr._count, - stats->_nmethods_size, stats->_nmethods_code_size); + print_times(comp); } } } diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/compiler/compileBroker.hpp --- a/src/share/vm/compiler/compileBroker.hpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/compiler/compileBroker.hpp Tue Jun 03 11:51:27 2014 +0200 @@ -438,6 +438,11 @@ // Redefine Classes support static void mark_on_stack(); +#ifdef GRAAL + // Print curent compilation time stats for a given compiler + static void print_times(AbstractCompiler* comp); +#endif + // Print a detailed accounting of compilation time static void print_times(bool per_compiler = true, bool aggregate = true); diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -25,7 +25,6 @@ #include "memory/oopFactory.hpp" #include "runtime/javaCalls.hpp" #include "graal/graalCompiler.hpp" -#include "graal/graalVMToCompiler.hpp" #include "graal/graalEnv.hpp" #include "graal/graalRuntime.hpp" #include "runtime/compilationPolicy.hpp" @@ -35,7 +34,7 @@ GraalCompiler::GraalCompiler() : AbstractCompiler(graal) { #ifdef COMPILERGRAAL - _started = false; + _bootstrapping = false; #endif assert(_instance == NULL, "only one instance allowed"); _instance = this; @@ -63,15 +62,15 @@ { HandleMark hm; - bool bootstrap = UseGraalCompilationQueue && (FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal); - VMToCompiler::startCompiler(bootstrap); - _started = true; + _bootstrapping = UseGraalCompilationQueue && (FLAG_IS_DEFAULT(BootstrapGraal) ? !TieredCompilation : BootstrapGraal); + + start_compilation_queue(); // Graal is considered as application code so we need to // stop the VM deferring compilation now. CompilationPolicy::completed_vm_startup(); - if (bootstrap) { + if (_bootstrapping) { // Avoid -Xcomp and -Xbatch problems by turning on interpreter and background compilation for bootstrapping. FlagSetting a(UseInterpreter, true); FlagSetting b(BackgroundCompilation, true); @@ -81,12 +80,12 @@ // allowing a complete bootstrap FlagSetting c(CompileTheWorld, false); #endif - VMToCompiler::bootstrap(); + bootstrap(); } #ifndef PRODUCT if (CompileTheWorld) { - VMToCompiler::compileTheWorld(); + compile_the_world(); } #endif } @@ -94,18 +93,58 @@ } #ifdef COMPILERGRAAL +void GraalCompiler::start_compilation_queue() { + JavaThread* THREAD = JavaThread::current(); + HandleMark hm(THREAD); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/CompilationQueue", THREAD); + KlassHandle klass = GraalRuntime::load_required_class(name); + NoGraalCompilationScheduling ngcs(THREAD); + klass->initialize(THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling start_compilation_queue"); +} + + +void GraalCompiler::shutdown_compilation_queue() { + JavaThread* THREAD = JavaThread::current(); + HandleMark hm(THREAD); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/CompilationQueue", THREAD); + KlassHandle klass = GraalRuntime::load_required_class(name); + JavaValue result(T_VOID); + JavaCallArguments args; + JavaCalls::call_static(&result, klass, vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling shutdown_compilation_queue"); +} + +void GraalCompiler::bootstrap() { + JavaThread* THREAD = JavaThread::current(); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/CompilationQueue", THREAD); + KlassHandle klass = GraalRuntime::load_required_class(name); + JavaValue result(T_VOID); + TempNewSymbol bootstrap = SymbolTable::new_symbol("bootstrap", THREAD); + NoGraalCompilationScheduling ngcs(THREAD); + JavaCalls::call_static(&result, klass, bootstrap, vmSymbols::void_method_signature(), THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling bootstrap"); +} + void GraalCompiler::compile_method(methodHandle method, int entry_bci, CompileTask* task, jboolean blocking) { GRAAL_EXCEPTION_CONTEXT - if (!_started) { - CompilationPolicy::policy()->delay_compilation(method()); - return; + + bool is_osr = entry_bci != InvocationEntryBci; + if (_bootstrapping && is_osr) { + // no OSR compilations during bootstrap - the compiler is just too slow at this point, + // and we know that there are no endless loops + return; } - assert(_started, "must already be started"); ResourceMark rm; - thread->set_is_graal_compiling(true); - VMToCompiler::compileMethod(method(), entry_bci, (jlong) (address) task, blocking); - thread->set_is_graal_compiling(false); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_long((jlong) (address) method()); + args.push_int(entry_bci); + args.push_long((jlong) (address) task); + args.push_int(blocking); + JavaCalls::call_static(&result, SystemDictionary::CompilationTask_klass(), vmSymbols::compileMetaspaceMethod_name(), vmSymbols::compileMetaspaceMethod_signature(), &args, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling compile_method"); } @@ -115,10 +154,7 @@ } void GraalCompiler::shutdown() { - if (_started) { - VMToCompiler::shutdownCompiler(); - _started = false; - } + shutdown_compilation_queue(); } // Print compilation timers and statistics @@ -127,3 +163,21 @@ } #endif // COMPILERGRAAL + +#ifndef PRODUCT +void GraalCompiler::compile_the_world() { + // We turn off CompileTheWorld so that Graal can + // be compiled by C1/C2 when Graal does a CTW. + CompileTheWorld = false; + + JavaThread* THREAD = JavaThread::current(); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD); + KlassHandle klass = GraalRuntime::load_required_class(name); + TempNewSymbol compileTheWorld = SymbolTable::new_symbol("compileTheWorld", THREAD); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(GraalRuntime::get_HotSpotGraalRuntime()); + JavaCalls::call_special(&result, klass, compileTheWorld, vmSymbols::void_method_signature(), &args, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling compile_the_world"); +} +#endif diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/graal/graalCompiler.hpp Tue Jun 03 11:51:27 2014 +0200 @@ -31,8 +31,11 @@ private: #ifdef COMPILERGRAAL - // Set to true once VMToCompiler.startCompiler() returns - bool _started; + bool _bootstrapping; + + void start_compilation_queue(); + void shutdown_compilation_queue(); + void bootstrap(); #endif static GraalCompiler* _instance; @@ -66,8 +69,46 @@ // Print compilation timers and statistics virtual void print_timers(); + // Print compilation statistics + void reset_compilation_stats(); + void shutdown(); +#endif // COMPILERGRAAL + +#ifndef PRODUCT + void compile_the_world(); #endif }; +#ifdef COMPILERGRAAL +/** + * Creates a scope in which scheduling a Graal compilation is disabled. + * Scheduling a compilation can happen anywhere a counter can overflow and + * calling back into the Java code for scheduling a compilation (i.e., + * CompilationTask.compileMetaspaceMethod()) from such arbitrary locations + * can cause objects to be in an unexpected state. + * + * In addition, it can be useful to disable compilation scheduling in + * other circumstances such as when initializing the Graal compilation + * queue or when running the Graal bootstrap process. + */ +class NoGraalCompilationScheduling: public StackObj { + private: + JavaThread* _thread; + public: + + NoGraalCompilationScheduling(JavaThread *thread) { + assert(thread == JavaThread::current(), "not the current thread"); + assert(thread->can_schedule_graal_compilation(), "recursive Graal compilation scheduling"); + _thread = thread; + thread->set_can_schedule_graal_compilation(false); + } + + ~NoGraalCompilationScheduling() { + assert(!_thread->can_schedule_graal_compilation(), "unexpected Graal compilation scheduling state"); + _thread->set_can_schedule_graal_compilation(true); + } +}; +#endif // COMPILERGRAAL + #endif // SHARE_VM_GRAAL_GRAAL_COMPILER_HPP diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -37,7 +37,6 @@ #include "graal/graalEnv.hpp" #include "graal/graalJavaAccess.hpp" #include "graal/graalCodeInstaller.hpp" -#include "graal/graalVMToCompiler.hpp" #include "gc_implementation/g1/heapRegion.hpp" #include "runtime/javaCalls.hpp" #include "runtime/deoptimization.hpp" @@ -515,18 +514,10 @@ } C2V_END -C2V_VMENTRY(void, printCompilationStatistics, (JNIEnv *jniEnv, jobject, jboolean per_compiler, jboolean aggregate)) - CompileBroker::print_times(per_compiler == JNI_TRUE, aggregate == JNI_TRUE); -C2V_END - C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv *jniEnv, jobject)) CompilerStatistics* stats = GraalCompiler::instance()->stats(); - stats->_standard._time.reset(); - stats->_standard._bytes = 0; - stats->_standard._count = 0; - stats->_osr._time.reset(); - stats->_osr._bytes = 0; - stats->_osr._count = 0; + stats->_standard.reset(); + stats->_osr.reset(); C2V_END C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob)) @@ -1042,7 +1033,6 @@ {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, {CC"installCode0", CC"("HS_COMPILED_CODE INSTALLED_CODE SPECULATION_LOG")I", FN_PTR(installCode0)}, {CC"notifyCompilationStatistics", CC"(I"HS_RESOLVED_METHOD"ZIJJ"INSTALLED_CODE")V", FN_PTR(notifyCompilationStatistics)}, - {CC"printCompilationStatistics", CC"(ZZ)V", FN_PTR(printCompilationStatistics)}, {CC"resetCompilationStatistics", CC"()V", FN_PTR(resetCompilationStatistics)}, {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, {CC"executeCompiledMethodVarargs", CC"(["OBJECT INSTALLED_CODE")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -23,9 +23,10 @@ #include "precompiled.hpp" #include "asm/codeBuffer.hpp" +#include "compiler/compileBroker.hpp" #include "graal/graalRuntime.hpp" -#include "graal/graalVMToCompiler.hpp" #include "graal/graalCompilerToVM.hpp" +#include "graal/graalCompiler.hpp" #include "graal/graalJavaAccess.hpp" #include "graal/graalEnv.hpp" #include "memory/oopFactory.hpp" @@ -37,6 +38,7 @@ #include "utilities/debug.hpp" address GraalRuntime::_external_deopt_i2c_entry = NULL; +jobject GraalRuntime::_HotSpotGraalRuntime_instance = NULL; void GraalRuntime::initialize_natives(JNIEnv *env, jclass c2vmClass) { uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end(); @@ -60,7 +62,7 @@ env->RegisterNatives(c2vmClass, CompilerToVM_methods, CompilerToVM_methods_count()); } - check_pending_exception("Could not register natives"); + GUARANTEE_NO_PENDING_EXCEPTION("Could not register natives"); } BufferBlob* GraalRuntime::initialize_buffer_blob() { @@ -638,7 +640,7 @@ // private static GraalRuntime Graal.initializeRuntime() JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c)) - return VMToCompiler::get_HotSpotGraalRuntime_jobject(); + return GraalRuntime::get_HotSpotGraalRuntime_jobject(); JVM_END // private static String[] Graal.getServiceImpls(Class service) @@ -650,11 +652,34 @@ // private static TruffleRuntime Truffle.createRuntime() JVM_ENTRY(jobject, JVM_CreateTruffleRuntime(JNIEnv *env, jclass c)) - return JNIHandles::make_local(VMToCompiler::create_HotSpotTruffleRuntime()()); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime", THREAD); + KlassHandle klass = GraalRuntime::load_required_class(name); + + TempNewSymbol makeInstance = SymbolTable::new_symbol("makeInstance", THREAD); + TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime;", THREAD); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, klass, makeInstance, sig, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Couldn't initialize HotSpotTruffleRuntime"); + return JNIHandles::make_local((oop) result.get_jobject()); JVM_END -// private static void HotSpotGraalRuntime.init(Class compilerToVMClass) -JVM_ENTRY(void, JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass c2vmClass)) +Handle GraalRuntime::get_HotSpotGraalRuntime() { + if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) { + Thread* THREAD = Thread::current(); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD); + KlassHandle klass = load_required_class(name); + TempNewSymbol runtime = SymbolTable::new_symbol("runtime", THREAD); + TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;", THREAD); + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, klass, runtime, sig, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Couldn't initialize HotSpotGraalRuntime"); + _HotSpotGraalRuntime_instance = JNIHandles::make_global((oop) result.get_jobject()); + } + return Handle(JNIHandles::resolve_non_null(_HotSpotGraalRuntime_instance)); +} + +// private static void CompilerToVMImpl.init() +JVM_ENTRY(void, JVM_InitializeGraalNatives(JNIEnv *env, jclass c2vmClass)) GraalRuntime::initialize_natives(env, c2vmClass); JVM_END @@ -665,6 +690,17 @@ return GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false); JVM_END +#ifdef COMPILERGRAAL +// private static boolean CompilationQueue.printAndResetCompRate() +JVM_ENTRY(void, JVM_PrintAndResetGraalCompRate(JNIEnv *env, jclass c)) + GraalCompiler* comp = GraalCompiler::instance(); + CompileBroker::print_times(comp); + CompilerStatistics* stats = comp->stats(); + stats->_standard.reset(); + stats->_osr.reset(); +JVM_END +#endif + bool GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) { ResourceMark rm(THREAD); @@ -712,7 +748,7 @@ } if (!valid) { - VMToCompiler::setOption(hotSpotOptionsClass, name_handle, Handle(), ' ', Handle(), 0L); + set_option_helper(hotSpotOptionsClass, name_handle, Handle(), ' ', Handle(), 0L); char buf[200]; jio_snprintf(buf, sizeof(buf), "Invalid Graal option %s", arg); THROW_MSG(vmSymbols::java_lang_InternalError(), buf); @@ -797,6 +833,21 @@ THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); } +void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { + Thread* THREAD = Thread::current(); + TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD); + TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(name()); + args.push_oop(option()); + args.push_int(spec); + args.push_oop(stringValue()); + args.push_long(primitiveValue); + JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling set_option_helper"); +} + Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) { TempNewSymbol name = SymbolTable::new_symbol(declaringClass, THREAD); Klass* klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NH); @@ -832,4 +883,47 @@ return service; } +void GraalRuntime::shutdown() { + if (_HotSpotGraalRuntime_instance != NULL) { + JavaThread* THREAD = JavaThread::current(); + HandleMark hm(THREAD); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD); + KlassHandle klass = load_required_class(name); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(get_HotSpotGraalRuntime()); + JavaCalls::call_special(&result, klass, vmSymbols::shutdown_method_name(), vmSymbols::void_method_signature(), &args, THREAD); + GUARANTEE_NO_PENDING_EXCEPTION("Error while calling shutdown"); + + JNIHandles::destroy_global(_HotSpotGraalRuntime_instance); + _HotSpotGraalRuntime_instance = NULL; + } +} + +void GraalRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) { + Thread* THREAD = Thread::current(); + CLEAR_PENDING_EXCEPTION; + + assert(exception->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected"); + JavaValue result(T_VOID); + JavaCalls::call_virtual(&result, + exception, + KlassHandle(THREAD, + SystemDictionary::Throwable_klass()), + vmSymbols::printStackTrace_name(), + vmSymbols::void_method_signature(), + THREAD); + + vm_abort(dump_core); +} + +Klass* GraalRuntime::load_required_class(Symbol* name) { + Klass* klass = SystemDictionary::resolve_or_null(name, SystemDictionary::java_system_loader(), Handle(), Thread::current()); + if (klass == NULL) { + tty->print_cr("Could not load class %s", name->as_C_string()); + vm_abort(false); + } + return klass; +} + #include "graalRuntime.inline.hpp" diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Jun 03 11:51:27 2014 +0200 @@ -31,6 +31,7 @@ class GraalRuntime: public CHeapObj { private: + static jobject _HotSpotGraalRuntime_instance; static address _external_deopt_i2c_entry; /** @@ -77,6 +78,11 @@ static bool set_option(KlassHandle hotSpotOptionsClass, const char* name, int name_len, Handle name_handle, const char* value, TRAPS); /** + * Java call to HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) + */ + static void set_option_helper(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); + + /** * Instantiates a service object, calls its default constructor and returns it. * * @param name the name of a class implementing com.oracle.graal.api.runtime.Service @@ -87,6 +93,20 @@ static void initialize_natives(JNIEnv *env, jclass c2vmClass); + static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_instance != NULL; } + + /** + * Gets the singleton HotSpotGraalRuntime instance, initializing it if necessary + */ + static Handle get_HotSpotGraalRuntime(); + + static jobject get_HotSpotGraalRuntime_jobject() { + get_HotSpotGraalRuntime(); + return _HotSpotGraalRuntime_instance; + } + + static void shutdown(); + /** * Given an interface representing a Graal service (i.e. sub-interface of * com.oracle.graal.api.runtime.Service), gets an array of objects, one per @@ -97,6 +117,19 @@ */ static Handle get_service_impls(KlassHandle serviceKlass, TRAPS); + /** + * Aborts the VM due to an unexpected exception. + */ + static void abort_on_pending_exception(Handle exception, const char* message, bool dump_core = false); + +#define GUARANTEE_NO_PENDING_EXCEPTION(error_message) do { \ + if (HAS_PENDING_EXCEPTION) { \ + GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, error_message); \ + } \ + } while (0); + + static Klass* load_required_class(Symbol* name); + static BufferBlob* initialize_buffer_blob(); static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS); diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Tue Jun 03 11:01:58 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "classfile/systemDictionary.hpp" -#include "graal/graalVMToCompiler.hpp" -#include "runtime/gpu.hpp" - -// these are *global* handles -jobject VMToCompiler::_HotSpotGraalRuntime_instance = NULL; -jobject VMToCompiler::_VMToCompiler_instance = NULL; -Klass* VMToCompiler::_VMToCompiler_klass = NULL; - -static Klass* loadClass(Symbol* name) { - Klass* klass = SystemDictionary::resolve_or_null(name, SystemDictionary::java_system_loader(), Handle(), Thread::current()); - if (klass == NULL) { - tty->print_cr("Could not load class %s", name->as_C_string()); - vm_abort(false); - } - return klass; -} - -KlassHandle VMToCompiler::VMToCompiler_klass() { - if (_VMToCompiler_klass == NULL) { - TempNewSymbol VMToCompiler = SymbolTable::new_symbol("com/oracle/graal/hotspot/bridge/VMToCompiler", Thread::current()); - Klass* result = loadClass(VMToCompiler); - _VMToCompiler_klass = result; - } - return _VMToCompiler_klass; -} - -Handle VMToCompiler::create_HotSpotTruffleRuntime() { - Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime", THREAD); - KlassHandle klass = loadClass(name); - - TempNewSymbol makeInstance = SymbolTable::new_symbol("makeInstance", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime;", THREAD); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, klass, makeInstance, sig, THREAD); - check_pending_exception("Couldn't initialize HotSpotTruffleRuntime"); - return Handle((oop) result.get_jobject()); -} - -Handle VMToCompiler::get_HotSpotGraalRuntime() { - if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) { - Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD); - KlassHandle klass = loadClass(name); - TempNewSymbol runtime = SymbolTable::new_symbol("runtime", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;", THREAD); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, klass, runtime, sig, THREAD); - check_pending_exception("Couldn't initialize HotSpotGraalRuntime"); - _HotSpotGraalRuntime_instance = JNIHandles::make_global((oop) result.get_jobject()); - } - return Handle(JNIHandles::resolve_non_null(_HotSpotGraalRuntime_instance)); -} - -Handle VMToCompiler::VMToCompiler_instance() { - if (JNIHandles::resolve(_VMToCompiler_instance) == NULL) { - Thread* THREAD = Thread::current(); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", THREAD); - KlassHandle klass = loadClass(name); - TempNewSymbol getVMToCompiler = SymbolTable::new_symbol("getVMToCompiler", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;", THREAD); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.set_receiver(get_HotSpotGraalRuntime()); - JavaCalls::call_virtual(&result, klass, getVMToCompiler, sig, &args, THREAD); - check_pending_exception("Couldn't get VMToCompiler"); - _VMToCompiler_instance = JNIHandles::make_global((oop) result.get_jobject()); - } - return Handle(JNIHandles::resolve_non_null(_VMToCompiler_instance)); -} - -void VMToCompiler::setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { - assert(!option.is_null(), "npe"); - Thread* THREAD = Thread::current(); - TempNewSymbol setOption = SymbolTable::new_symbol("setOption", THREAD); - TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", THREAD); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(name()); - args.push_oop(option()); - args.push_int(spec); - args.push_oop(stringValue()); - args.push_long(primitiveValue); - JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, THREAD); - check_pending_exception("Error while calling setOption"); -} - -#ifdef COMPILERGRAAL -void VMToCompiler::bootstrap() { - JavaThread* THREAD = JavaThread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - TempNewSymbol bootstrap = SymbolTable::new_symbol("bootstrap", THREAD); - args.push_oop(VMToCompiler_instance()); - JavaCalls::call_interface(&result, VMToCompiler_klass(), bootstrap, vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling bootstrap"); -} - -void VMToCompiler::startCompiler(jboolean bootstrap_enabled) { - JavaThread* THREAD = JavaThread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - TempNewSymbol startCompiler = SymbolTable::new_symbol("startCompiler", THREAD); - args.push_oop(VMToCompiler_instance()); - args.push_int(bootstrap_enabled); - JavaCalls::call_interface(&result, VMToCompiler_klass(), startCompiler, vmSymbols::bool_void_signature(), &args, THREAD); - check_pending_exception("Error while calling startCompiler"); -} - -void VMToCompiler::compileMethod(Method* method, int entry_bci, jlong ctask, jboolean blocking) { - assert(method != NULL, "just checking"); - Thread* THREAD = Thread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(VMToCompiler_instance()); - args.push_long((jlong) (address) method); - args.push_int(entry_bci); - args.push_long(ctask); - args.push_int(blocking); - JavaCalls::call_interface(&result, VMToCompiler_klass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD); - check_pending_exception("Error while calling compileMethod"); -} - -void VMToCompiler::shutdownCompiler() { - JavaThread* THREAD = JavaThread::current(); - HandleMark hm(THREAD); - TempNewSymbol shutdownCompiler = SymbolTable::new_symbol("shutdownCompiler", THREAD); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(VMToCompiler_instance()); - JavaCalls::call_interface(&result, VMToCompiler_klass(), shutdownCompiler, vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling shutdownCompiler"); -} -#endif // COMPILERGRAAL - -void VMToCompiler::shutdownRuntime() { - if (_HotSpotGraalRuntime_instance != NULL) { - JavaThread* THREAD = JavaThread::current(); - HandleMark hm(THREAD); - TempNewSymbol shutdownRuntime = SymbolTable::new_symbol("shutdownRuntime", THREAD); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(VMToCompiler_instance()); - JavaCalls::call_interface(&result, VMToCompiler_klass(), shutdownRuntime, vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling shutdownRuntime"); - - JNIHandles::destroy_global(_HotSpotGraalRuntime_instance); - JNIHandles::destroy_global(_VMToCompiler_instance); - - _HotSpotGraalRuntime_instance = NULL; - _VMToCompiler_instance = NULL; - _VMToCompiler_klass = NULL; - } -} - -#ifndef PRODUCT -void VMToCompiler::compileTheWorld() { - // We turn off CompileTheWorld so that Graal can - // be compiled by C1/C2 when Graal does a CTW. - CompileTheWorld = false; - - JavaThread* THREAD = JavaThread::current(); - TempNewSymbol compileTheWorld = SymbolTable::new_symbol("compileTheWorld", THREAD); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(VMToCompiler_instance()); - JavaCalls::call_interface(&result, VMToCompiler_klass(), compileTheWorld, vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling compileTheWorld"); -} -#endif diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Tue Jun 03 11:01:58 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#ifndef SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP -#define SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP - -#include "memory/allocation.hpp" -#include "oops/oop.hpp" -#include "runtime/handles.hpp" -#include "runtime/thread.hpp" -#include "classfile/javaClasses.hpp" -#include "runtime/jniHandles.hpp" -#include "runtime/javaCalls.hpp" - -class VMToCompiler : public AllStatic { - -private: - static jobject _HotSpotGraalRuntime_instance; - static jobject _VMToCompiler_instance; - - static Klass* _VMToCompiler_klass; - - static KlassHandle VMToCompiler_klass(); - static Handle VMToCompiler_instance(); - -public: - - static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_instance != NULL; } - - // Gets the singleton HotSpotGraalRuntime instance, initializing it if necessary - static Handle get_HotSpotGraalRuntime(); - - // Creates a new HotSpotTruffleRuntime object - static Handle create_HotSpotTruffleRuntime(); - - static jobject get_HotSpotGraalRuntime_jobject() { - get_HotSpotGraalRuntime(); - return _HotSpotGraalRuntime_instance; - } - - // public static void HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue); - static void setOption(KlassHandle hotSpotOptionsClass, Handle name, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); - -#ifdef COMPILERGRAAL - // public abstract void startCompiler(boolean bootstrapEnabled); - static void startCompiler(jboolean bootstrap_enabled); - - // public abstract void bootstrap(); - static void bootstrap(); - - // public abstract boolean compileMethod(long metaspaceMethod, int entryBCI, long ctask, boolean blocking); - static void compileMethod(Method* method, int entry_bci, jlong ctask, jboolean blocking); - - // public abstract void shutdownCompiler(); - static void shutdownCompiler(); -#endif - - // public abstract void shutdownRuntime(); - static void shutdownRuntime(); - -#ifndef PRODUCT - // public abstract void compileTheWorld(); - static void compileTheWorld(); -#endif -}; - -inline void check_pending_exception(const char* message, bool dump_core = false) { - Thread* THREAD = Thread::current(); - if (THREAD->has_pending_exception()) { - Handle exception = PENDING_EXCEPTION; - CLEAR_PENDING_EXCEPTION; - - assert(exception->is_a(SystemDictionary::Throwable_klass()), "Throwable instance expected"); - JavaValue result(T_VOID); - JavaCalls::call_virtual(&result, - exception, - KlassHandle(THREAD, - SystemDictionary::Throwable_klass()), - vmSymbols::printStackTrace_name(), - vmSymbols::void_method_signature(), - THREAD); - - vm_abort(dump_core); - } -} - -#endif // SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -61,7 +61,7 @@ #include "utilities/macros.hpp" #ifdef GRAAL #include "classfile/javaAssertions.hpp" -#include "graal/graalVMToCompiler.hpp" +#include "graal/graalRuntime.hpp" #endif #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" @@ -1209,7 +1209,7 @@ #ifdef GRAAL if (this_oop->is_subtype_of(SystemDictionary::Node_klass())) { if (this_oop() != SystemDictionary::Node_klass()) { - if (!VMToCompiler::is_HotSpotGraalRuntime_initialized() && JavaAssertions::systemClassDefault() == false) { + if (!GraalRuntime::is_HotSpotGraalRuntime_initialized() && JavaAssertions::systemClassDefault() == false) { // We want to ensure that the process of initializing HotSpotGraalRuntime // is fast since it executes at VM startup. We must avoid triggering // class initialization of any Node classes during this process. diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/prims/jni.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -35,7 +35,7 @@ #include "utilities/macros.hpp" #ifdef GRAAL #include "graal/graalCompiler.hpp" -#include "graal/graalVMToCompiler.hpp" +#include "graal/graalRuntime.hpp" #endif #if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" @@ -5218,7 +5218,7 @@ // stop the VM deferring compilation now. CompilationPolicy::completed_vm_startup(); - VMToCompiler::compileTheWorld(); + GraalCompiler::instance()->compile_the_world(); } #endif #else diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/prims/nativeLookup.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -124,11 +124,14 @@ void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); #ifdef GRAAL - void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass c, jclass compilerToVMClass); + void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass compilerToVMClass); jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); jobject JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c); jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass); +#ifdef COMPILERGRAAL + void JNICALL JVM_PrintAndResetGraalCompRate(JNIEnv *env, jclass c); +#endif #endif } @@ -141,11 +144,14 @@ { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, #ifdef GRAAL - { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, - { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls", NULL, FN_PTR(JVM_GetGraalServiceImpls) }, - { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotGraalRuntime_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, + { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, + { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls", NULL, FN_PTR(JVM_GetGraalServiceImpls) }, + { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, + { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, +#ifdef COMPILERGRAAL + { CC"Java_com_oracle_graal_hotspot_CompilationQueue_printAndResetCompRate", NULL, FN_PTR(JVM_PrintAndResetGraalCompRate)}, +#endif #endif }; diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/runtime/java.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -32,7 +32,7 @@ #include "interpreter/bytecodeHistogram.hpp" #ifdef GRAAL #include "graal/graalCompiler.hpp" -#include "graal/graalVMToCompiler.hpp" +#include "graal/graalRuntime.hpp" #endif #include "memory/genCollectedHeap.hpp" #include "memory/oopFactory.hpp" @@ -489,7 +489,7 @@ GraalCompiler::instance()->shutdown(); } #endif - VMToCompiler::shutdownRuntime(); + GraalRuntime::shutdown(); #endif // The only difference between this and Win32's _onexit procs is that diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/runtime/thread.cpp Tue Jun 03 11:51:27 2014 +0200 @@ -1483,7 +1483,7 @@ #ifdef GRAAL _graal_alternate_call_target = NULL; _graal_implicit_exception_pc = NULL; - _graal_compiling = false; + _graal_can_schedule_compilation = true; if (GraalCounterSize > 0) { _graal_counters = NEW_C_HEAP_ARRAY(jlong, GraalCounterSize, mtInternal); memset(_graal_counters, 0, sizeof(jlong) * GraalCounterSize); diff -r 83433cf49019 -r 66a9286203a2 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Tue Jun 03 11:01:58 2014 +0200 +++ b/src/share/vm/runtime/thread.hpp Tue Jun 03 11:51:27 2014 +0200 @@ -922,8 +922,8 @@ #ifdef GRAAL address _graal_alternate_call_target; - address _graal_implicit_exception_pc; // pc at which the most recent implicit exception occurred - bool _graal_compiling; + address _graal_implicit_exception_pc; // pc at which the most recent implicit exception occurred + bool _graal_can_schedule_compilation; // see NoGraalCompilationScheduling jlong* _graal_counters; @@ -1310,8 +1310,8 @@ #ifdef GRAAL void set_graal_alternate_call_target(address a) { _graal_alternate_call_target = a; } void set_graal_implicit_exception_pc(address a) { _graal_implicit_exception_pc = a; } - bool is_graal_compiling() { return _graal_compiling; } - void set_is_graal_compiling(bool b) { _graal_compiling = b; } + bool can_schedule_graal_compilation() { return _graal_can_schedule_compilation; } + void set_can_schedule_graal_compilation(bool b) { _graal_can_schedule_compilation = b; } #endif // Exception handling for compiled methods