16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.core; 24 25 import java.util.Collection; 26 import java.util.List; 27 28 import org.graalvm.compiler.code.CompilationResult; 29 import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; 30 import org.graalvm.compiler.core.common.GraalOptions; 31 import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; 32 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; 33 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 34 import org.graalvm.compiler.core.common.util.CompilationAlarm; 35 import org.graalvm.compiler.core.target.Backend; 36 import org.graalvm.compiler.debug.Debug; 37 import org.graalvm.compiler.debug.Debug.Scope; 38 import org.graalvm.compiler.debug.DebugCloseable; 39 import org.graalvm.compiler.debug.DebugCounter; 40 import org.graalvm.compiler.debug.DebugTimer; 41 import org.graalvm.compiler.debug.GraalError; 42 import org.graalvm.compiler.debug.MethodFilter; 43 import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; 44 import org.graalvm.compiler.lir.LIR; 45 import org.graalvm.compiler.lir.alloc.OutOfRegistersException; 46 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 47 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; 48 import org.graalvm.compiler.lir.framemap.FrameMap; 49 import org.graalvm.compiler.lir.framemap.FrameMapBuilder; 50 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 51 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 52 import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; 53 import org.graalvm.compiler.lir.phases.LIRSuites; 54 import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; 55 import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; 56 import org.graalvm.compiler.nodes.StructuredGraph; 57 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; 58 import org.graalvm.compiler.nodes.cfg.Block; 59 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 60 import org.graalvm.compiler.phases.OptimisticOptimizations; 61 import org.graalvm.compiler.phases.PhaseSuite; 62 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; 63 import org.graalvm.compiler.phases.tiers.HighTierContext; 68 import org.graalvm.compiler.phases.util.Providers; 69 import org.graalvm.util.EconomicSet; 70 71 import jdk.vm.ci.code.RegisterConfig; 72 import jdk.vm.ci.code.TargetDescription; 73 import jdk.vm.ci.code.site.ConstantReference; 74 import jdk.vm.ci.code.site.DataPatch; 75 import jdk.vm.ci.meta.Assumptions; 76 import jdk.vm.ci.meta.JavaConstant; 77 import jdk.vm.ci.meta.JavaKind; 78 import jdk.vm.ci.meta.ProfilingInfo; 79 import jdk.vm.ci.meta.ResolvedJavaField; 80 import jdk.vm.ci.meta.ResolvedJavaMethod; 81 import jdk.vm.ci.meta.VMConstant; 82 83 /** 84 * Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}. 85 */ 86 public class GraalCompiler { 87 88 private static final DebugTimer CompilerTimer = Debug.timer("GraalCompiler"); 89 private static final DebugTimer FrontEnd = Debug.timer("FrontEnd"); 90 private static final DebugTimer BackEnd = Debug.timer("BackEnd"); 91 private static final DebugTimer EmitLIR = Debug.timer("EmitLIR"); 92 private static final DebugTimer EmitCode = Debug.timer("EmitCode"); 93 94 /** 95 * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}. 96 */ 97 public static class Request<T extends CompilationResult> { 98 public final StructuredGraph graph; 99 public final ResolvedJavaMethod installedCodeOwner; 100 public final Providers providers; 101 public final Backend backend; 102 public final PhaseSuite<HighTierContext> graphBuilderSuite; 103 public final OptimisticOptimizations optimisticOpts; 104 public final ProfilingInfo profilingInfo; 105 public final Suites suites; 106 public final LIRSuites lirSuites; 107 public final T compilationResult; 108 public final CompilationResultBuilderFactory factory; 109 110 /** 111 * @param graph the graph to be compiled 112 * @param installedCodeOwner the method the compiled code will be associated with once 150 * Requests compilation of a given graph. 151 * 152 * @param graph the graph to be compiled 153 * @param installedCodeOwner the method the compiled code will be associated with once 154 * installed. This argument can be null. 155 * @return the result of the compilation 156 */ 157 public static <T extends CompilationResult> T compileGraph(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, 158 PhaseSuite<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, 159 CompilationResultBuilderFactory factory) { 160 return compile(new Request<>(graph, installedCodeOwner, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory)); 161 } 162 163 /** 164 * Services a given compilation request. 165 * 166 * @return the result of the compilation 167 */ 168 @SuppressWarnings("try") 169 public static <T extends CompilationResult> T compile(Request<T> r) { 170 try (Scope s = MethodMetricsRootScopeInfo.createRootScopeIfAbsent(r.installedCodeOwner); 171 CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { 172 assert !r.graph.isFrozen(); 173 try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start()) { 174 emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); 175 emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites); 176 } catch (Throwable e) { 177 throw Debug.handle(e); 178 } 179 checkForRequestedCrash(r.graph); 180 return r.compilationResult; 181 } 182 } 183 184 /** 185 * Checks whether the {@link GraalCompilerOptions#CrashAt} option indicates that the compilation 186 * of {@code graph} should result in an exception. 187 * 188 * @param graph a graph currently being compiled 189 * @throws RuntimeException if the value of {@link GraalCompilerOptions#CrashAt} matches 190 * {@code graph.method()} or {@code graph.name} 191 */ 192 private static void checkForRequestedCrash(StructuredGraph graph) { 193 String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions()); 194 if (methodPattern != null) { 195 String crashLabel = null; 196 if (graph.name != null && graph.name.contains(methodPattern)) { 197 crashLabel = graph.name; 200 ResolvedJavaMethod method = graph.method(); 201 MethodFilter[] filters = MethodFilter.parse(methodPattern); 202 for (MethodFilter filter : filters) { 203 if (filter.matches(method)) { 204 crashLabel = method.format("%H.%n(%p)"); 205 } 206 } 207 } 208 if (crashLabel != null) { 209 throw new RuntimeException("Forced crash after compiling " + crashLabel); 210 } 211 } 212 } 213 214 /** 215 * Builds the graph, optimizes it. 216 */ 217 @SuppressWarnings("try") 218 public static void emitFrontEnd(Providers providers, TargetProvider target, StructuredGraph graph, PhaseSuite<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts, 219 ProfilingInfo profilingInfo, Suites suites) { 220 try (Scope s = Debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start()) { 221 HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts); 222 if (graph.start().next() == null) { 223 graphBuilderSuite.apply(graph, highTierContext); 224 new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph); 225 Debug.dump(Debug.BASIC_LEVEL, graph, "After parsing"); 226 } else { 227 Debug.dump(Debug.INFO_LEVEL, graph, "initial state"); 228 } 229 230 suites.getHighTier().apply(graph, highTierContext); 231 graph.maybeCompress(); 232 Debug.dump(Debug.BASIC_LEVEL, graph, "After high tier"); 233 234 MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo); 235 suites.getMidTier().apply(graph, midTierContext); 236 graph.maybeCompress(); 237 Debug.dump(Debug.BASIC_LEVEL, graph, "After mid tier"); 238 239 LowTierContext lowTierContext = new LowTierContext(providers, target); 240 suites.getLowTier().apply(graph, lowTierContext); 241 Debug.dump(Debug.BASIC_LEVEL, graph, "After low tier"); 242 243 Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); 244 } catch (Throwable e) { 245 throw Debug.handle(e); 246 } finally { 247 graph.checkCancellation(); 248 } 249 } 250 251 @SuppressWarnings("try") 252 public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, 253 CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { 254 try (Scope s = Debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start()) { 255 LIRGenerationResult lirGen = null; 256 lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites); 257 try (Scope s2 = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { 258 int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize(); 259 compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess()); 260 emitCode(backend, graph.getAssumptions(), graph.method(), graph.getMethods(), graph.getFields(), bytecodeSize, lirGen, compilationResult, installedCodeOwner, factory); 261 } catch (Throwable e) { 262 throw Debug.handle(e); 263 } 264 } catch (Throwable e) { 265 throw Debug.handle(e); 266 } finally { 267 graph.checkCancellation(); 268 } 269 } 270 271 @SuppressWarnings("try") 272 public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { 273 String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); 274 String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); 275 try { 276 return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); 277 } catch (OutOfRegistersException e) { 278 if (allocationRestrictedTo != null) { 279 allocationRestrictedTo = null; 280 return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); 281 } 282 /* If the re-execution fails we convert the exception into a "hard" failure */ 283 throw new GraalError(e); 284 } finally { 285 graph.checkCancellation(); 286 } 287 } 288 289 @SuppressWarnings("try") 290 private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, 291 String[] allocationRestrictedTo) { 292 try (Scope ds = Debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start()) { 293 assert !graph.hasValueProxies(); 294 ScheduleResult schedule = graph.getLastSchedule(); 295 Block[] blocks = schedule.getCFG().getBlocks(); 296 Block startBlock = schedule.getCFG().getStartBlock(); 297 assert startBlock != null; 298 assert startBlock.getPredecessorCount() == 0; 299 300 AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); 301 AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); 302 LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions()); 303 304 FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig); 305 LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub); 306 LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes); 307 NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen); 308 309 // LIR generation 310 LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); 311 new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); 312 313 try (Scope s = Debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { 314 // Dump LIR along with HIR (the LIR is looked up from context) 315 Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation"); 316 LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo)); 317 return result; 318 } catch (Throwable e) { 319 throw Debug.handle(e); 320 } 321 } catch (Throwable e) { 322 throw Debug.handle(e); 323 } finally { 324 graph.checkCancellation(); 325 } 326 } 327 328 protected static <T extends CompilationResult> String getCompilationUnitName(StructuredGraph graph, T compilationResult) { 329 if (compilationResult != null && compilationResult.getName() != null) { 330 return compilationResult.getName(); 331 } 332 ResolvedJavaMethod method = graph.method(); 333 if (method == null) { 334 return "<unknown>"; 335 } 336 return method.format("%H.%n(%p)"); 337 } 338 339 public static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites, 340 RegisterAllocationConfig registerAllocationConfig) { 341 PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen); 342 lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext); 343 Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); 344 345 AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); 346 lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext); 347 Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); 348 349 PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); 350 lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext); 351 Debug.dump(Debug.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); 352 353 return lirGenRes; 354 } 355 356 @SuppressWarnings("try") 357 public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods, EconomicSet<ResolvedJavaField> accessedFields, 358 int bytecodeSize, LIRGenerationResult lirGenRes, 359 CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { 360 try (DebugCloseable a = EmitCode.start()) { 361 FrameMap frameMap = lirGenRes.getFrameMap(); 362 CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); 363 backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); 364 if (assumptions != null && !assumptions.isEmpty()) { 365 compilationResult.setAssumptions(assumptions.toArray()); 366 } 367 if (rootMethod != null) { 368 compilationResult.setMethods(rootMethod, inlinedMethods); 369 compilationResult.setFields(accessedFields); 370 compilationResult.setBytecodeSize(bytecodeSize); 371 } 372 crb.finish(); 373 if (Debug.isCountEnabled()) { 374 List<DataPatch> ldp = compilationResult.getDataPatches(); 375 JavaKind[] kindValues = JavaKind.values(); 376 DebugCounter[] dms = new DebugCounter[kindValues.length]; 377 for (int i = 0; i < dms.length; i++) { 378 dms[i] = Debug.counter("DataPatches-%s", kindValues[i]); 379 } 380 381 for (DataPatch dp : ldp) { 382 JavaKind kind = JavaKind.Illegal; 383 if (dp.reference instanceof ConstantReference) { 384 VMConstant constant = ((ConstantReference) dp.reference).getConstant(); 385 if (constant instanceof JavaConstant) { 386 kind = ((JavaConstant) constant).getJavaKind(); 387 } 388 } 389 dms[kind.ordinal()].add(1); 390 } 391 392 Debug.counter("CompilationResults").increment(); 393 Debug.counter("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); 394 Debug.counter("InfopointsEmitted").add(compilationResult.getInfopoints().size()); 395 Debug.counter("DataPatches").add(ldp.size()); 396 Debug.counter("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); 397 } 398 399 Debug.dump(Debug.BASIC_LEVEL, compilationResult, "After code generation"); 400 } 401 } 402 } | 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.core; 24 25 import java.util.Collection; 26 import java.util.List; 27 28 import org.graalvm.compiler.code.CompilationResult; 29 import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; 30 import org.graalvm.compiler.core.common.GraalOptions; 31 import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; 32 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; 33 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 34 import org.graalvm.compiler.core.common.util.CompilationAlarm; 35 import org.graalvm.compiler.core.target.Backend; 36 import org.graalvm.compiler.debug.CounterKey; 37 import org.graalvm.compiler.debug.DebugCloseable; 38 import org.graalvm.compiler.debug.DebugContext; 39 import org.graalvm.compiler.debug.GraalError; 40 import org.graalvm.compiler.debug.MethodFilter; 41 import org.graalvm.compiler.debug.TimerKey; 42 import org.graalvm.compiler.lir.LIR; 43 import org.graalvm.compiler.lir.alloc.OutOfRegistersException; 44 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 45 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; 46 import org.graalvm.compiler.lir.framemap.FrameMap; 47 import org.graalvm.compiler.lir.framemap.FrameMapBuilder; 48 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 49 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 50 import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext; 51 import org.graalvm.compiler.lir.phases.LIRSuites; 52 import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; 53 import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; 54 import org.graalvm.compiler.nodes.StructuredGraph; 55 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; 56 import org.graalvm.compiler.nodes.cfg.Block; 57 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 58 import org.graalvm.compiler.phases.OptimisticOptimizations; 59 import org.graalvm.compiler.phases.PhaseSuite; 60 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; 61 import org.graalvm.compiler.phases.tiers.HighTierContext; 66 import org.graalvm.compiler.phases.util.Providers; 67 import org.graalvm.util.EconomicSet; 68 69 import jdk.vm.ci.code.RegisterConfig; 70 import jdk.vm.ci.code.TargetDescription; 71 import jdk.vm.ci.code.site.ConstantReference; 72 import jdk.vm.ci.code.site.DataPatch; 73 import jdk.vm.ci.meta.Assumptions; 74 import jdk.vm.ci.meta.JavaConstant; 75 import jdk.vm.ci.meta.JavaKind; 76 import jdk.vm.ci.meta.ProfilingInfo; 77 import jdk.vm.ci.meta.ResolvedJavaField; 78 import jdk.vm.ci.meta.ResolvedJavaMethod; 79 import jdk.vm.ci.meta.VMConstant; 80 81 /** 82 * Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}. 83 */ 84 public class GraalCompiler { 85 86 private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation)."); 87 private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR."); 88 private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR."); 89 private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR."); 90 private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode."); 91 92 /** 93 * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}. 94 */ 95 public static class Request<T extends CompilationResult> { 96 public final StructuredGraph graph; 97 public final ResolvedJavaMethod installedCodeOwner; 98 public final Providers providers; 99 public final Backend backend; 100 public final PhaseSuite<HighTierContext> graphBuilderSuite; 101 public final OptimisticOptimizations optimisticOpts; 102 public final ProfilingInfo profilingInfo; 103 public final Suites suites; 104 public final LIRSuites lirSuites; 105 public final T compilationResult; 106 public final CompilationResultBuilderFactory factory; 107 108 /** 109 * @param graph the graph to be compiled 110 * @param installedCodeOwner the method the compiled code will be associated with once 148 * Requests compilation of a given graph. 149 * 150 * @param graph the graph to be compiled 151 * @param installedCodeOwner the method the compiled code will be associated with once 152 * installed. This argument can be null. 153 * @return the result of the compilation 154 */ 155 public static <T extends CompilationResult> T compileGraph(StructuredGraph graph, ResolvedJavaMethod installedCodeOwner, Providers providers, Backend backend, 156 PhaseSuite<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites, LIRSuites lirSuites, T compilationResult, 157 CompilationResultBuilderFactory factory) { 158 return compile(new Request<>(graph, installedCodeOwner, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, compilationResult, factory)); 159 } 160 161 /** 162 * Services a given compilation request. 163 * 164 * @return the result of the compilation 165 */ 166 @SuppressWarnings("try") 167 public static <T extends CompilationResult> T compile(Request<T> r) { 168 DebugContext debug = r.graph.getDebug(); 169 try (CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { 170 assert !r.graph.isFrozen(); 171 try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) { 172 emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); 173 emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites); 174 } catch (Throwable e) { 175 throw debug.handle(e); 176 } 177 checkForRequestedCrash(r.graph); 178 return r.compilationResult; 179 } 180 } 181 182 /** 183 * Checks whether the {@link GraalCompilerOptions#CrashAt} option indicates that the compilation 184 * of {@code graph} should result in an exception. 185 * 186 * @param graph a graph currently being compiled 187 * @throws RuntimeException if the value of {@link GraalCompilerOptions#CrashAt} matches 188 * {@code graph.method()} or {@code graph.name} 189 */ 190 private static void checkForRequestedCrash(StructuredGraph graph) { 191 String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions()); 192 if (methodPattern != null) { 193 String crashLabel = null; 194 if (graph.name != null && graph.name.contains(methodPattern)) { 195 crashLabel = graph.name; 198 ResolvedJavaMethod method = graph.method(); 199 MethodFilter[] filters = MethodFilter.parse(methodPattern); 200 for (MethodFilter filter : filters) { 201 if (filter.matches(method)) { 202 crashLabel = method.format("%H.%n(%p)"); 203 } 204 } 205 } 206 if (crashLabel != null) { 207 throw new RuntimeException("Forced crash after compiling " + crashLabel); 208 } 209 } 210 } 211 212 /** 213 * Builds the graph, optimizes it. 214 */ 215 @SuppressWarnings("try") 216 public static void emitFrontEnd(Providers providers, TargetProvider target, StructuredGraph graph, PhaseSuite<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts, 217 ProfilingInfo profilingInfo, Suites suites) { 218 DebugContext debug = graph.getDebug(); 219 try (DebugContext.Scope s = debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start(debug)) { 220 HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts); 221 if (graph.start().next() == null) { 222 graphBuilderSuite.apply(graph, highTierContext); 223 new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph); 224 debug.dump(DebugContext.BASIC_LEVEL, graph, "After parsing"); 225 } else { 226 debug.dump(DebugContext.INFO_LEVEL, graph, "initial state"); 227 } 228 229 suites.getHighTier().apply(graph, highTierContext); 230 graph.maybeCompress(); 231 debug.dump(DebugContext.BASIC_LEVEL, graph, "After high tier"); 232 233 MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo); 234 suites.getMidTier().apply(graph, midTierContext); 235 graph.maybeCompress(); 236 debug.dump(DebugContext.BASIC_LEVEL, graph, "After mid tier"); 237 238 LowTierContext lowTierContext = new LowTierContext(providers, target); 239 suites.getLowTier().apply(graph, lowTierContext); 240 debug.dump(DebugContext.BASIC_LEVEL, graph, "After low tier"); 241 242 debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); 243 } catch (Throwable e) { 244 throw debug.handle(e); 245 } finally { 246 graph.checkCancellation(); 247 } 248 } 249 250 @SuppressWarnings("try") 251 public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, 252 CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { 253 DebugContext debug = graph.getDebug(); 254 try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) { 255 LIRGenerationResult lirGen = null; 256 lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites); 257 try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) { 258 int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize(); 259 compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess()); 260 emitCode(backend, graph.getAssumptions(), graph.method(), graph.getMethods(), graph.getFields(), bytecodeSize, lirGen, compilationResult, installedCodeOwner, factory); 261 } catch (Throwable e) { 262 throw debug.handle(e); 263 } 264 } catch (Throwable e) { 265 throw debug.handle(e); 266 } finally { 267 graph.checkCancellation(); 268 } 269 } 270 271 @SuppressWarnings("try") 272 public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { 273 String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); 274 String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); 275 try { 276 return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); 277 } catch (OutOfRegistersException e) { 278 if (allocationRestrictedTo != null) { 279 allocationRestrictedTo = null; 280 return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); 281 } 282 /* If the re-execution fails we convert the exception into a "hard" failure */ 283 throw new GraalError(e); 284 } finally { 285 graph.checkCancellation(); 286 } 287 } 288 289 @SuppressWarnings("try") 290 private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, 291 String[] allocationRestrictedTo) { 292 DebugContext debug = graph.getDebug(); 293 try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) { 294 assert !graph.hasValueProxies(); 295 ScheduleResult schedule = graph.getLastSchedule(); 296 Block[] blocks = schedule.getCFG().getBlocks(); 297 Block startBlock = schedule.getCFG().getStartBlock(); 298 assert startBlock != null; 299 assert startBlock.getPredecessorCount() == 0; 300 301 AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); 302 AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); 303 LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug()); 304 305 FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig); 306 LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub); 307 LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes); 308 NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen); 309 310 // LIR generation 311 LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); 312 new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); 313 314 try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { 315 // Dump LIR along with HIR (the LIR is looked up from context) 316 debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation"); 317 LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo)); 318 return result; 319 } catch (Throwable e) { 320 throw debug.handle(e); 321 } 322 } catch (Throwable e) { 323 throw debug.handle(e); 324 } finally { 325 graph.checkCancellation(); 326 } 327 } 328 329 protected static <T extends CompilationResult> String getCompilationUnitName(StructuredGraph graph, T compilationResult) { 330 if (compilationResult != null && compilationResult.getName() != null) { 331 return compilationResult.getName(); 332 } 333 ResolvedJavaMethod method = graph.method(); 334 if (method == null) { 335 return "<unknown>"; 336 } 337 return method.format("%H.%n(%p)"); 338 } 339 340 public static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites, 341 RegisterAllocationConfig registerAllocationConfig) { 342 DebugContext debug = lirGenRes.getLIR().getDebug(); 343 PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen); 344 lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext); 345 debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); 346 347 AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); 348 lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext); 349 debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); 350 351 PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); 352 lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext); 353 debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); 354 355 return lirGenRes; 356 } 357 358 @SuppressWarnings("try") 359 public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods, EconomicSet<ResolvedJavaField> accessedFields, 360 int bytecodeSize, LIRGenerationResult lirGenRes, 361 CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { 362 DebugContext debug = lirGenRes.getLIR().getDebug(); 363 try (DebugCloseable a = EmitCode.start(debug)) { 364 FrameMap frameMap = lirGenRes.getFrameMap(); 365 CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); 366 backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); 367 if (assumptions != null && !assumptions.isEmpty()) { 368 compilationResult.setAssumptions(assumptions.toArray()); 369 } 370 if (rootMethod != null) { 371 compilationResult.setMethods(rootMethod, inlinedMethods); 372 compilationResult.setFields(accessedFields); 373 compilationResult.setBytecodeSize(bytecodeSize); 374 } 375 crb.finish(); 376 if (debug.isCountEnabled()) { 377 List<DataPatch> ldp = compilationResult.getDataPatches(); 378 JavaKind[] kindValues = JavaKind.values(); 379 CounterKey[] dms = new CounterKey[kindValues.length]; 380 for (int i = 0; i < dms.length; i++) { 381 dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]); 382 } 383 384 for (DataPatch dp : ldp) { 385 JavaKind kind = JavaKind.Illegal; 386 if (dp.reference instanceof ConstantReference) { 387 VMConstant constant = ((ConstantReference) dp.reference).getConstant(); 388 if (constant instanceof JavaConstant) { 389 kind = ((JavaConstant) constant).getJavaKind(); 390 } 391 } 392 dms[kind.ordinal()].add(debug, 1); 393 } 394 395 DebugContext.counter("CompilationResults").increment(debug); 396 DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize()); 397 DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size()); 398 DebugContext.counter("DataPatches").add(debug, ldp.size()); 399 DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size()); 400 } 401 402 debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation"); 403 } 404 } 405 } |