1 /* 2 * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 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 24 package jdk.tools.jaotc; 25 26 import java.util.concurrent.TimeUnit; 27 import java.util.concurrent.atomic.AtomicInteger; 28 29 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 30 import org.graalvm.compiler.code.CompilationResult; 31 import org.graalvm.compiler.core.GraalCompilerOptions; 32 import org.graalvm.compiler.debug.DebugContext; 33 import org.graalvm.compiler.debug.Management; 34 import org.graalvm.compiler.debug.TTY; 35 import org.graalvm.compiler.debug.DebugContext.Activation; 36 import org.graalvm.compiler.options.OptionValues; 37 import org.graalvm.compiler.printer.GraalDebugHandlersFactory; 38 39 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 40 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 41 import jdk.vm.ci.meta.ResolvedJavaMethod; 42 import jdk.vm.ci.runtime.JVMCICompiler; 43 44 /** 45 * Represents a task in the compile queue. 46 * 47 * This class encapsulates all Graal-specific information that is used during offline AOT 48 * compilation of classes. It also defines methods that parse compilation result of Graal to create 49 * target-independent representation {@code BinaryContainer} of the intended target binary. 50 */ 51 public class AOTCompilationTask implements Runnable, Comparable<Object> { 52 53 private static final AtomicInteger ids = new AtomicInteger(); 54 55 private static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); 56 57 private final Main main; 58 59 private OptionValues graalOptions; 60 61 /** 62 * The compilation id of this task. 63 */ 64 private final int id; 65 66 private final AOTCompiledClass holder; 67 68 /** 69 * Method this task represents. 70 */ 71 private final ResolvedJavaMethod method; 72 73 private final AOTBackend aotBackend; 74 75 /** 76 * The result of this compilation task. 77 */ 78 private CompiledMethodInfo result; 79 80 public AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { 81 this.main = main; 82 this.graalOptions = graalOptions; 83 this.id = ids.incrementAndGet(); 84 this.holder = holder; 85 this.method = method; 86 this.aotBackend = aotBackend; 87 } 88 89 /** 90 * Compile a method or a constructor. 91 */ 92 @SuppressWarnings("try") 93 public void run() { 94 // Ensure a JVMCI runtime is initialized prior to Debug being initialized as the former 95 // may include processing command line options used by the latter. 96 HotSpotJVMCIRuntime.runtime(); 97 98 AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling"); 99 100 final long threadId = Thread.currentThread().getId(); 101 102 final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed(); 103 final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue(graalOptions) && !TTY.isSuppressed(); 104 if (printCompilation) { 105 TTY.println(getMethodDescription() + "..."); 106 } 107 108 final long start; 109 final long allocatedBytesBefore; 110 if (printAfterCompilation || printCompilation) { 111 start = System.currentTimeMillis(); 112 allocatedBytesBefore = printAfterCompilation || printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L; 113 } else { 114 start = 0L; 115 allocatedBytesBefore = 0L; 116 } 117 118 CompilationResult compResult = null; 119 final long startTime = System.currentTimeMillis(); 120 SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); 121 try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) { 122 compResult = aotBackend.compileMethod(method, debug); 123 } 124 final long endTime = System.currentTimeMillis(); 125 126 if (printAfterCompilation || printCompilation) { 127 final long stop = System.currentTimeMillis(); 128 final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1; 129 final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId); 130 final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; 131 132 TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes)); 133 } 134 135 if (compResult == null) { 136 result = null; 137 return; 138 } 139 140 // For now precision to the nearest second is sufficient. 141 Main.writeLog(" Compile Time: " + TimeUnit.MILLISECONDS.toSeconds(endTime - startTime) + "secs"); 142 if (main.options.debug) { 143 aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult); 144 } 145 146 result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend())); 147 } 148 149 private String getMethodDescription() { 150 return String.format("%-6d aot %s %s", getId(), MiscUtils.uniqueMethodName(method), 151 getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); 152 } 153 154 private int getId() { 155 return id; 156 } 157 158 public int getEntryBCI() { 159 return JVMCICompiler.INVOCATION_ENTRY_BCI; 160 } 161 162 public ResolvedJavaMethod getMethod() { 163 return method; 164 } 165 166 /** 167 * Returns the holder of this method as a {@link AOTCompiledClass}. 168 * 169 * @return the holder of this method 170 */ 171 public AOTCompiledClass getHolder() { 172 return holder; 173 } 174 175 /** 176 * Returns the result of this compilation task. 177 * 178 * @return result of this compilation task 179 */ 180 public CompiledMethodInfo getResult() { 181 return result; 182 } 183 184 @Override 185 public int compareTo(Object obj) { 186 AOTCompilationTask other = (AOTCompilationTask) obj; 187 return this.id - other.id; 188 } 189 190 @Override 191 public boolean equals(Object obj) { 192 if (this == obj) 193 return true; 194 if (obj == null) 195 return false; 196 if (getClass() != obj.getClass()) 197 return false; 198 AOTCompilationTask other = (AOTCompilationTask) obj; 199 return (this.id == other.id); 200 } 201 202 @Override 203 public int hashCode() { 204 return 31 + id; 205 } 206 207 }