HotSpotGraalCompiler.java revision 13522:0c2d710aa6df
1130803Smarcel/* 2130803Smarcel * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3130803Smarcel * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4130803Smarcel * 5130803Smarcel * This code is free software; you can redistribute it and/or modify it 6130803Smarcel * under the terms of the GNU General Public License version 2 only, as 7130803Smarcel * published by the Free Software Foundation. 8130803Smarcel * 9130803Smarcel * This code is distributed in the hope that it will be useful, but WITHOUT 10130803Smarcel * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11130803Smarcel * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12130803Smarcel * version 2 for more details (a copy is included in the LICENSE file that 13130803Smarcel * accompanied this code). 14130803Smarcel * 15130803Smarcel * You should have received a copy of the GNU General Public License version 16130803Smarcel * 2 along with this work; if not, write to the Free Software Foundation, 17130803Smarcel * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18130803Smarcel * 19130803Smarcel * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20130803Smarcel * or visit www.oracle.com if you need additional information or have any 21130803Smarcel * questions. 22130803Smarcel */ 23130803Smarcelpackage org.graalvm.compiler.hotspot; 24130803Smarcel 25130803Smarcelimport static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; 26130803Smarcelimport static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; 27130803Smarcel 28130803Smarcelimport java.io.ByteArrayOutputStream; 29130803Smarcelimport java.io.PrintStream; 30130803Smarcelimport java.util.Collections; 31130803Smarcelimport java.util.Formattable; 32130803Smarcelimport java.util.Formatter; 33130803Smarcelimport java.util.List; 34130803Smarcel 35130803Smarcelimport org.graalvm.compiler.api.runtime.GraalJVMCICompiler; 36130803Smarcelimport org.graalvm.compiler.bytecode.Bytecode; 37130803Smarcelimport org.graalvm.compiler.code.CompilationResult; 38130803Smarcelimport org.graalvm.compiler.core.GraalCompiler; 39130803Smarcelimport org.graalvm.compiler.core.common.CompilationIdentifier; 40130803Smarcelimport org.graalvm.compiler.core.common.util.CompilationAlarm; 41130803Smarcelimport org.graalvm.compiler.debug.DebugHandlersFactory; 42130803Smarcelimport org.graalvm.compiler.debug.DebugContext; 43130803Smarcelimport org.graalvm.compiler.debug.DebugContext.Activation; 44130803Smarcelimport org.graalvm.compiler.debug.DebugOptions; 45130803Smarcelimport org.graalvm.compiler.hotspot.CompilationCounters.Options; 46130803Smarcelimport org.graalvm.compiler.hotspot.meta.HotSpotProviders; 47130803Smarcelimport org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; 48130803Smarcelimport org.graalvm.compiler.java.GraphBuilderPhase; 49130803Smarcelimport org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; 50130803Smarcelimport org.graalvm.compiler.lir.phases.LIRSuites; 51130803Smarcelimport org.graalvm.compiler.nodes.StructuredGraph; 52130803Smarcelimport org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 53130803Smarcelimport org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 54130803Smarcelimport org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; 55130803Smarcelimport org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; 56130803Smarcelimport org.graalvm.compiler.nodes.spi.Replacements; 57130803Smarcelimport org.graalvm.compiler.options.OptionValues; 58130803Smarcelimport org.graalvm.compiler.phases.OptimisticOptimizations; 59130803Smarcelimport org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; 60130803Smarcelimport org.graalvm.compiler.phases.PhaseSuite; 61130803Smarcelimport org.graalvm.compiler.phases.tiers.HighTierContext; 62130803Smarcelimport org.graalvm.compiler.phases.tiers.Suites; 63130803Smarcelimport org.graalvm.compiler.printer.GraalDebugHandlersFactory; 64130803Smarcel 65130803Smarcelimport jdk.vm.ci.code.CompilationRequest; 66130803Smarcelimport jdk.vm.ci.code.CompilationRequestResult; 67130803Smarcelimport jdk.vm.ci.hotspot.HotSpotCompilationRequest; 68130803Smarcelimport jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; 69130803Smarcelimport jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; 70130803Smarcelimport jdk.vm.ci.meta.DefaultProfilingInfo; 71130803Smarcelimport jdk.vm.ci.meta.JavaMethod; 72130803Smarcelimport jdk.vm.ci.meta.ProfilingInfo; 73130803Smarcelimport jdk.vm.ci.meta.ResolvedJavaMethod; 74130803Smarcelimport jdk.vm.ci.meta.SpeculationLog; 75130803Smarcelimport jdk.vm.ci.meta.TriState; 76130803Smarcelimport jdk.vm.ci.runtime.JVMCICompiler; 77130803Smarcel 78130803Smarcelpublic class HotSpotGraalCompiler implements GraalJVMCICompiler { 79130803Smarcel 80130803Smarcel private final HotSpotJVMCIRuntimeProvider jvmciRuntime; 81130803Smarcel private final HotSpotGraalRuntimeProvider graalRuntime; 82130803Smarcel private final CompilationCounters compilationCounters; 83130803Smarcel private final BootstrapWatchDog bootstrapWatchDog; 84130803Smarcel private List<DebugHandlersFactory> factories; 85130803Smarcel 86130803Smarcel HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, OptionValues options) { 87130803Smarcel this.jvmciRuntime = jvmciRuntime; 88130803Smarcel this.graalRuntime = graalRuntime; 89 // It is sufficient to have one compilation counter object per Graal compiler object. 90 this.compilationCounters = Options.CompilationCountLimit.getValue(options) > 0 ? new CompilationCounters(options) : null; 91 this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !DebugOptions.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; 92 } 93 94 public List<DebugHandlersFactory> getDebugHandlersFactories() { 95 if (factories == null) { 96 factories = Collections.singletonList(new GraalDebugHandlersFactory(graalRuntime.getHostProviders().getSnippetReflection())); 97 } 98 return factories; 99 } 100 101 @Override 102 public HotSpotGraalRuntimeProvider getGraalRuntime() { 103 return graalRuntime; 104 } 105 106 @Override 107 public CompilationRequestResult compileMethod(CompilationRequest request) { 108 return compileMethod(request, true); 109 } 110 111 @SuppressWarnings("try") 112 CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault) { 113 if (graalRuntime.isShutdown()) { 114 return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false); 115 } 116 117 ResolvedJavaMethod method = request.getMethod(); 118 OptionValues options = graalRuntime.getOptions(method); 119 120 if (graalRuntime.isBootstrapping()) { 121 if (DebugOptions.BootstrapInitializeOnly.getValue(options)) { 122 return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true); 123 } 124 if (bootstrapWatchDog != null) { 125 if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { 126 // Drain the compilation queue to expedite completion of the bootstrap 127 return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); 128 } 129 } 130 } 131 HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request; 132 try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options); 133 BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); 134 CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) { 135 if (compilationCounters != null) { 136 compilationCounters.countCompilation(method); 137 } 138 CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, installAsDefault, options); 139 CompilationRequestResult r = null; 140 try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories()); 141 Activation a = debug.activate()) { 142 r = task.runCompilation(debug); 143 } 144 assert r != null; 145 return r; 146 } 147 } 148 149 public StructuredGraph createGraph(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { 150 HotSpotBackend backend = graalRuntime.getHostBackend(); 151 HotSpotProviders providers = backend.getProviders(); 152 final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; 153 StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId, options, debug); 154 155 if (graph == null) { 156 SpeculationLog speculationLog = method.getSpeculationLog(); 157 if (speculationLog != null) { 158 speculationLog.collectFailedSpeculations(); 159 } 160 graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog( 161 speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build(); 162 } 163 return graph; 164 } 165 166 public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, 167 OptionValues options) { 168 169 HotSpotBackend backend = graalRuntime.getHostBackend(); 170 HotSpotProviders providers = backend.getProviders(); 171 final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; 172 173 Suites suites = getSuites(providers, options); 174 LIRSuites lirSuites = getLIRSuites(providers, options); 175 ProfilingInfo profilingInfo = useProfilingInfo ? method.getProfilingInfo(!isOSR, isOSR) : DefaultProfilingInfo.get(TriState.FALSE); 176 OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo, options); 177 178 /* 179 * Cut off never executed code profiles if there is code, e.g. after the osr loop, that is 180 * never executed. 181 */ 182 if (isOSR && !OnStackReplacementPhase.Options.DeoptAfterOSR.getValue(options)) { 183 optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); 184 } 185 186 result.setEntryBCI(entryBCI); 187 boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints(); 188 PhaseSuite<HighTierContext> graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR); 189 GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf); 190 191 if (!isOSR && useProfilingInfo) { 192 ProfilingInfo profile = profilingInfo; 193 profile.setCompilerIRSize(StructuredGraph.class, graph.getNodeCount()); 194 } 195 196 return result; 197 } 198 199 public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { 200 StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug); 201 CompilationResult result = new CompilationResult(compilationId); 202 return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options); 203 } 204 205 /** 206 * Gets a graph produced from the intrinsic for a given method that can be compiled and 207 * installed for the method. 208 * 209 * @param method 210 * @param compilationId 211 * @param options 212 * @param debug 213 * @return an intrinsic graph that can be compiled and installed for {@code method} or null 214 */ 215 @SuppressWarnings("try") 216 public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { 217 Replacements replacements = providers.getReplacements(); 218 Bytecode subst = replacements.getSubstitutionBytecode(method); 219 if (subst != null) { 220 ResolvedJavaMethod substMethod = subst.getMethod(); 221 assert !substMethod.equals(method); 222 StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(substMethod).compilationId(compilationId).build(); 223 try (DebugContext.Scope scope = debug.scope("GetIntrinsicGraph", graph)) { 224 Plugins plugins = new Plugins(providers.getGraphBuilderPlugins()); 225 GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); 226 IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, subst.getOrigin(), ROOT_COMPILATION); 227 new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, 228 OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); 229 assert !graph.isFrozen(); 230 return graph; 231 } catch (Throwable e) { 232 debug.handle(e); 233 } 234 } 235 return null; 236 } 237 238 protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo, OptionValues options) { 239 return new OptimisticOptimizations(profilingInfo, options); 240 } 241 242 protected Suites getSuites(HotSpotProviders providers, OptionValues options) { 243 return providers.getSuites().getDefaultSuites(options); 244 } 245 246 protected LIRSuites getLIRSuites(HotSpotProviders providers, OptionValues options) { 247 return providers.getSuites().getDefaultLIRSuites(options); 248 } 249 250 /** 251 * Reconfigures a given graph builder suite (GBS) if one of the given GBS parameter values is 252 * not the default. 253 * 254 * @param suite the graph builder suite 255 * @param shouldDebugNonSafepoints specifies if extra debug info should be generated (default is 256 * false) 257 * @param isOSR specifies if extra OSR-specific post-processing is required (default is false) 258 * @return a new suite derived from {@code suite} if any of the GBS parameters did not have a 259 * default value otherwise {@code suite} 260 */ 261 protected PhaseSuite<HighTierContext> configGraphBuilderSuite(PhaseSuite<HighTierContext> suite, boolean shouldDebugNonSafepoints, boolean isOSR) { 262 if (shouldDebugNonSafepoints || isOSR) { 263 PhaseSuite<HighTierContext> newGbs = suite.copy(); 264 265 if (shouldDebugNonSafepoints) { 266 GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); 267 GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); 268 graphBuilderConfig = graphBuilderConfig.withNodeSourcePosition(true); 269 GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); 270 newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); 271 } 272 if (isOSR) { 273 // We must not clear non liveness for OSR compilations. 274 GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); 275 GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); 276 GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); 277 newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); 278 newGbs.appendPhase(new OnStackReplacementPhase()); 279 } 280 return newGbs; 281 } 282 return suite; 283 } 284 285 /** 286 * Converts {@code method} to a String with {@link JavaMethod#format(String)} and the format 287 * string {@code "%H.%n(%p)"}. 288 */ 289 static String str(JavaMethod method) { 290 return method.format("%H.%n(%p)"); 291 } 292 293 /** 294 * Wraps {@code obj} in a {@link Formatter} that standardizes formatting for certain objects. 295 */ 296 static Formattable fmt(Object obj) { 297 return new Formattable() { 298 @Override 299 public void formatTo(Formatter buf, int flags, int width, int precision) { 300 if (obj instanceof Throwable) { 301 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 302 ((Throwable) obj).printStackTrace(new PrintStream(baos)); 303 buf.format("%s", baos.toString()); 304 } else if (obj instanceof StackTraceElement[]) { 305 for (StackTraceElement e : (StackTraceElement[]) obj) { 306 buf.format("\t%s%n", e); 307 } 308 } else if (obj instanceof JavaMethod) { 309 buf.format("%s", str((JavaMethod) obj)); 310 } else { 311 buf.format("%s", obj); 312 } 313 } 314 }; 315 } 316} 317