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 24package jdk.tools.jaotc; 25 26import java.util.concurrent.TimeUnit; 27import java.util.concurrent.atomic.AtomicInteger; 28 29import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 30import org.graalvm.compiler.code.CompilationResult; 31import org.graalvm.compiler.core.GraalCompilerOptions; 32import org.graalvm.compiler.debug.DebugContext; 33import org.graalvm.compiler.debug.Management; 34import org.graalvm.compiler.debug.TTY; 35import org.graalvm.compiler.debug.DebugContext.Activation; 36import org.graalvm.compiler.options.OptionValues; 37import org.graalvm.compiler.printer.GraalDebugHandlersFactory; 38 39import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 40import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 41import jdk.vm.ci.meta.ResolvedJavaMethod; 42import 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 */ 51final 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 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(JavaMethodInfo.uniqueMethodName(method), "Compiling"); 99 100 final long threadId = Thread.currentThread().getId(); 101 102 final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed(); 103 if (printCompilation) { 104 TTY.println(getMethodDescription() + "..."); 105 } 106 107 final long start; 108 final long allocatedBytesBefore; 109 if (printCompilation) { 110 start = System.currentTimeMillis(); 111 allocatedBytesBefore = printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L; 112 } else { 113 start = 0L; 114 allocatedBytesBefore = 0L; 115 } 116 117 CompilationResult compResult = null; 118 final long startTime = System.currentTimeMillis(); 119 SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); 120 try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) { 121 compResult = aotBackend.compileMethod(method, debug); 122 } 123 final long endTime = System.currentTimeMillis(); 124 125 if (printCompilation) { 126 final long stop = System.currentTimeMillis(); 127 final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1; 128 final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId); 129 final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; 130 131 TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes)); 132 } 133 134 if (compResult == null) { 135 result = null; 136 return; 137 } 138 139 // For now precision to the nearest second is sufficient. 140 LogPrinter.writeLog(" Compile Time: " + TimeUnit.MILLISECONDS.toSeconds(endTime - startTime) + "secs"); 141 if (main.options.debug) { 142 aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult); 143 } 144 145 result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend())); 146 } 147 148 private String getMethodDescription() { 149 return String.format("%-6d aot %s %s", getId(), JavaMethodInfo.uniqueMethodName(method), 150 getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); 151 } 152 153 private int getId() { 154 return id; 155 } 156 157 private static int getEntryBCI() { 158 return JVMCICompiler.INVOCATION_ENTRY_BCI; 159 } 160 161 ResolvedJavaMethod getMethod() { 162 return method; 163 } 164 165 /** 166 * Returns the holder of this method as a {@link AOTCompiledClass}. 167 * 168 * @return the holder of this method 169 */ 170 AOTCompiledClass getHolder() { 171 return holder; 172 } 173 174 /** 175 * Returns the result of this compilation task. 176 * 177 * @return result of this compilation task 178 */ 179 CompiledMethodInfo getResult() { 180 return result; 181 } 182 183 @Override 184 public int compareTo(Object obj) { 185 AOTCompilationTask other = (AOTCompilationTask) obj; 186 return this.id - other.id; 187 } 188 189 @Override 190 public boolean equals(Object obj) { 191 if (this == obj) 192 return true; 193 if (obj == null) 194 return false; 195 if (getClass() != obj.getClass()) 196 return false; 197 AOTCompilationTask other = (AOTCompilationTask) obj; 198 return (this.id == other.id); 199 } 200 201 @Override 202 public int hashCode() { 203 return 31 + id; 204 } 205 206} 207