--- /dev/null 2017-01-22 10:16:57.869617664 -0800 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java 2017-02-15 16:59:39.195364974 -0800 @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot; + +import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; +import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; +import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Formattable; +import java.util.Formatter; + +import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.GraalCompiler; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.util.CompilationAlarm; +import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.debug.TopLevelDebugConfig; +import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; +import org.graalvm.compiler.hotspot.CompilationCounters.Options; +import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; +import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; +import org.graalvm.compiler.lir.phases.LIRSuites; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; +import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.Suites; + +import jdk.vm.ci.code.CompilationRequest; +import jdk.vm.ci.code.CompilationRequestResult; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; +import jdk.vm.ci.meta.DefaultProfilingInfo; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.TriState; +import jdk.vm.ci.runtime.JVMCICompiler; + +public class HotSpotGraalCompiler implements GraalJVMCICompiler { + + private final HotSpotJVMCIRuntimeProvider jvmciRuntime; + private final HotSpotGraalRuntimeProvider graalRuntime; + private final CompilationCounters compilationCounters; + private final BootstrapWatchDog bootstrapWatchDog; + + HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime) { + this.jvmciRuntime = jvmciRuntime; + this.graalRuntime = graalRuntime; + // It is sufficient to have one compilation counter object per Graal compiler object. + this.compilationCounters = Options.CompilationCountLimit.getValue() > 0 ? new CompilationCounters() : null; + this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue() ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; + } + + @Override + public HotSpotGraalRuntimeProvider getGraalRuntime() { + return graalRuntime; + } + + @Override + @SuppressWarnings("try") + public CompilationRequestResult compileMethod(CompilationRequest request) { + if (graalRuntime.isBootstrapping() && GraalDebugConfig.Options.BootstrapInitializeOnly.getValue()) { + return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", GraalDebugConfig.Options.BootstrapInitializeOnly.getName()), true); + } + if (bootstrapWatchDog != null && graalRuntime.isBootstrapping()) { + if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { + // Drain the compilation queue to expedite completion of the bootstrap + return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); + } + } + ResolvedJavaMethod method = request.getMethod(); + HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request; + try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId()); + BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); + CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod();) { + if (compilationCounters != null) { + compilationCounters.countCompilation(method); + } + // Ensure a debug configuration for this thread is initialized + if (Debug.isEnabled() && DebugScope.getConfig() == null) { + DebugEnvironment.initialize(TTY.out, graalRuntime.getHostProviders().getSnippetReflection()); + } + CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, true); + CompilationRequestResult r = null; + try (DebugConfigScope dcs = Debug.setConfig(new TopLevelDebugConfig()); + Debug.Scope s = Debug.methodMetricsScope("HotSpotGraalCompiler", MethodMetricsRootScopeInfo.create(method), true, method)) { + r = task.runCompilation(); + } + assert r != null; + return r; + } + } + + public void compileTheWorld() throws Throwable { + HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmciRuntime.getHostJVMCIBackend().getCodeCache(); + int iterations = CompileTheWorldOptions.CompileTheWorldIterations.getValue(); + for (int i = 0; i < iterations; i++) { + codeCache.resetCompilationStatistics(); + TTY.println("CompileTheWorld : iteration " + i); + CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, this); + ctw.compile(); + } + System.exit(0); + } + + public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId) { + HotSpotBackend backend = graalRuntime.getHostBackend(); + HotSpotProviders providers = backend.getProviders(); + final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId); + + if (graph == null) { + SpeculationLog speculationLog = method.getSpeculationLog(); + if (speculationLog != null) { + speculationLog.collectFailedSpeculations(); + } + graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()), speculationLog, useProfilingInfo, compilationId); + } + + Suites suites = getSuites(providers); + LIRSuites lirSuites = getLIRSuites(providers); + ProfilingInfo profilingInfo = useProfilingInfo ? method.getProfilingInfo(!isOSR, isOSR) : DefaultProfilingInfo.get(TriState.FALSE); + OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); + if (isOSR) { + // In OSR compiles, we cannot rely on never executed code profiles, because + // all code after the OSR loop is never executed. + optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); + } + CompilationResult result = new CompilationResult(); + result.setEntryBCI(entryBCI); + boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints(); + PhaseSuite graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR); + GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, CompilationResultBuilderFactory.Default); + + if (!isOSR && useProfilingInfo) { + ProfilingInfo profile = profilingInfo; + profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount()); + } + + return result; + } + + /** + * Gets a graph produced from the intrinsic for a given method that can be compiled and + * installed for the method. + * + * @param method + * @param compilationId + * @return an intrinsic graph that can be compiled and installed for {@code method} or null + */ + @SuppressWarnings("try") + public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId) { + Replacements replacements = providers.getReplacements(); + ResolvedJavaMethod substMethod = replacements.getSubstitutionMethod(method); + if (substMethod != null) { + assert !substMethod.equals(method); + StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES, NO_PROFILING_INFO, compilationId); + try (Debug.Scope scope = Debug.scope("GetIntrinsicGraph", graph)) { + Plugins plugins = new Plugins(providers.getGraphBuilderPlugins()); + GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); + IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, replacements.getReplacementBytecodeProvider(), ROOT_COMPILATION); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, + OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); + assert !graph.isFrozen(); + return graph; + } catch (Throwable e) { + Debug.handle(e); + } + } + return null; + } + + protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) { + return new OptimisticOptimizations(profilingInfo); + } + + protected Suites getSuites(HotSpotProviders providers) { + return providers.getSuites().getDefaultSuites(); + } + + protected LIRSuites getLIRSuites(HotSpotProviders providers) { + return providers.getSuites().getDefaultLIRSuites(); + } + + /** + * Reconfigures a given graph builder suite (GBS) if one of the given GBS parameter values is + * not the default. + * + * @param suite the graph builder suite + * @param shouldDebugNonSafepoints specifies if extra debug info should be generated (default is + * false) + * @param isOSR specifies if extra OSR-specific post-processing is required (default is false) + * @return a new suite derived from {@code suite} if any of the GBS parameters did not have a + * default value otherwise {@code suite} + */ + protected PhaseSuite configGraphBuilderSuite(PhaseSuite suite, boolean shouldDebugNonSafepoints, boolean isOSR) { + if (shouldDebugNonSafepoints || isOSR) { + PhaseSuite newGbs = suite.copy(); + + if (shouldDebugNonSafepoints) { + GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); + GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); + graphBuilderConfig = graphBuilderConfig.withNodeSourcePosition(true); + GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); + newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); + } + if (isOSR) { + newGbs.appendPhase(new OnStackReplacementPhase()); + } + return newGbs; + } + return suite; + } + + /** + * Converts {@code method} to a String with {@link JavaMethod#format(String)} and the format + * string {@code "%H.%n(%p)"}. + */ + static String str(JavaMethod method) { + return method.format("%H.%n(%p)"); + } + + /** + * Wraps {@code obj} in a {@link Formatter} that standardizes formatting for certain objects. + */ + static Formattable fmt(Object obj) { + return new Formattable() { + @Override + public void formatTo(Formatter buf, int flags, int width, int precision) { + if (obj instanceof Throwable) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ((Throwable) obj).printStackTrace(new PrintStream(baos)); + buf.format("%s", baos.toString()); + } else if (obj instanceof StackTraceElement[]) { + for (StackTraceElement e : (StackTraceElement[]) obj) { + buf.format("\t%s%n", e); + } + } else if (obj instanceof JavaMethod) { + buf.format("%s", str((JavaMethod) obj)); + } else { + buf.format("%s", obj); + } + } + }; + } +}