1 /* 2 * Copyright (c) 2016, 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.code.CompilationResult; 30 import org.graalvm.compiler.core.GraalCompilerOptions; 31 import org.graalvm.compiler.debug.Debug; 32 import org.graalvm.compiler.debug.DebugEnvironment; 33 import org.graalvm.compiler.debug.Management; 34 import org.graalvm.compiler.debug.TTY; 35 import org.graalvm.compiler.debug.internal.DebugScope; 36 import org.graalvm.compiler.options.OptionValues; 37 38 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 39 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 40 import jdk.vm.ci.meta.ResolvedJavaMethod; 41 import jdk.vm.ci.runtime.JVMCICompiler; 42 43 /** 44 * Represents a task in the compile queue. 45 * 46 * This class encapsulates all Graal-specific information that is used during offline AOT 47 * compilation of classes. It also defines methods that parse compilation result of Graal to create 48 * target-independent representation {@code BinaryContainer} of the intended target binary. 49 */ 50 public class AOTCompilationTask implements Runnable, Comparable<Object> { 51 52 private static final AtomicInteger ids = new AtomicInteger(); 53 54 private static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); 55 56 private final Main main; 57 58 private OptionValues graalOptions; 59 60 /** 61 * The compilation id of this task. 62 */ 63 private final int id; 64 65 private final AOTCompiledClass holder; 66 67 /** 68 * Method this task represents. 69 */ 70 private final ResolvedJavaMethod method; 71 72 private final AOTBackend aotBackend; 73 74 /** 75 * The result of this compilation task. 76 */ 77 private CompiledMethodInfo result; 78 79 public AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { 80 this.main = main; 81 this.graalOptions = graalOptions; 82 this.id = ids.getAndIncrement(); 83 this.holder = holder; 84 this.method = method; 85 this.aotBackend = aotBackend; 86 } 87 88 /** 89 * Compile a method or a constructor. 90 */ 91 public void run() { 92 // Ensure a JVMCI runtime is initialized prior to Debug being initialized as the former 93 // may include processing command line options used by the latter. 94 HotSpotJVMCIRuntime.runtime(); 95 96 // Ensure a debug configuration for this thread is initialized 97 if (Debug.isEnabled() && DebugScope.getConfig() == null) { 98 DebugEnvironment.ensureInitialized(graalOptions); 99 } 100 AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling"); 101 102 final long threadId = Thread.currentThread().getId(); 103 104 final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed(); 105 final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue(graalOptions) && !TTY.isSuppressed(); 106 if (printCompilation) { 107 TTY.println(getMethodDescription() + "..."); 108 } 109 110 final long start; 111 final long allocatedBytesBefore; 112 if (printAfterCompilation || printCompilation) { 113 start = System.currentTimeMillis(); 114 allocatedBytesBefore = printAfterCompilation || printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L; 115 } else { 116 start = 0L; 117 allocatedBytesBefore = 0L; 118 } 119 120 final long startTime = System.currentTimeMillis(); 121 CompilationResult compResult = aotBackend.compileMethod(method); 122 final long endTime = System.currentTimeMillis(); 123 124 if (printAfterCompilation || printCompilation) { 125 final long stop = System.currentTimeMillis(); 126 final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1; 127 final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId); 128 final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; 129 130 if (printAfterCompilation) { 131 TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes)); 132 } else if (printCompilation) { 133 TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dkB", getId(), "", "", "", stop - start, targetCodeSize, allocatedBytes)); 134 } 135 } 136 137 if (compResult == null) { 138 result = null; 139 return; 140 } 141 142 // For now precision to the nearest second is sufficient. 143 Main.writeLog(" Compile Time: " + TimeUnit.MILLISECONDS.toSeconds(endTime - startTime) + "secs"); 144 if (main.options.debug) { 145 aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult); 146 } 147 148 result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method)); 149 } 150 151 private String getMethodDescription() { 152 return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(), 153 getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); 154 } 155 156 private int getId() { 157 return id; 158 } 159 160 public int getEntryBCI() { 161 return JVMCICompiler.INVOCATION_ENTRY_BCI; 162 } 163 164 public ResolvedJavaMethod getMethod() { 165 return method; 166 } 167 168 /** 169 * Returns the holder of this method as a {@link AOTCompiledClass}. 170 * 171 * @return the holder of this method 172 */ 173 public AOTCompiledClass getHolder() { 174 return holder; 175 } 176 177 /** 178 * Returns the result of this compilation task. 179 * 180 * @return result of this compilation task 181 */ 182 public CompiledMethodInfo getResult() { 183 return result; 184 } 185 186 @Override 187 public int compareTo(Object obj) { 188 AOTCompilationTask other = (AOTCompilationTask) obj; 189 return this.id - other.id; 190 } 191 192 @Override 193 public boolean equals(Object obj) { 194 if (this == obj) 195 return true; 196 if (obj == null) 197 return false; 198 if (getClass() != obj.getClass()) 199 return false; 200 AOTCompilationTask other = (AOTCompilationTask) obj; 201 return (this.id == other.id); 202 } 203 204 @Override 205 public int hashCode() { 206 return 31 + id; 207 } 208 209 }