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 25 26 package jdk.tools.jaotc; 27 28 import java.util.concurrent.TimeUnit; 29 import java.util.concurrent.atomic.AtomicInteger; 30 31 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; 32 import org.graalvm.compiler.code.CompilationResult; 33 import org.graalvm.compiler.core.GraalCompilerOptions; 34 import org.graalvm.compiler.debug.DebugContext; 35 import org.graalvm.compiler.debug.DebugContext.Activation; 36 import org.graalvm.compiler.debug.TTY; 37 import org.graalvm.compiler.options.OptionValues; 38 import org.graalvm.compiler.printer.GraalDebugHandlersFactory; 39 import org.graalvm.compiler.serviceprovider.GraalServices; 40 41 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 42 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; 43 import jdk.vm.ci.meta.ResolvedJavaMethod; 44 import jdk.vm.ci.runtime.JVMCICompiler; 45 46 /** 47 * Represents a task in the compile queue. 48 * 49 * This class encapsulates all Graal-specific information that is used during offline AOT 50 * compilation of classes. It also defines methods that parse compilation result of Graal to create 51 * target-independent representation {@code BinaryContainer} of the intended target binary. 52 */ 53 final class AOTCompilationTask implements Runnable, Comparable<Object> { 54 55 private static final AtomicInteger ids = new AtomicInteger(); 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 @Override 93 @SuppressWarnings("try") 94 public void run() { 95 // Ensure a JVMCI runtime is initialized prior to Debug being initialized as the former 96 // may include processing command line options used by the latter. 97 HotSpotJVMCIRuntime.runtime(); 98 99 AOTCompiler.logCompilation(JavaMethodInfo.uniqueMethodName(method), "Compiling"); 100 101 final long threadId = Thread.currentThread().getId(); 102 103 final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed() && GraalServices.isThreadAllocatedMemorySupported(); 104 if (printCompilation) { 105 TTY.println(getMethodDescription() + "..."); 106 } 107 108 final long start; 109 final long allocatedBytesBefore; 110 if (printCompilation) { 111 start = System.currentTimeMillis(); 112 allocatedBytesBefore = GraalServices.getThreadAllocatedBytes(threadId); 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 (printCompilation) { 127 final long stop = System.currentTimeMillis(); 128 final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1; 129 final long allocatedBytesAfter = GraalServices.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 LogPrinter.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(), graalOptions)); 147 } 148 149 private String getMethodDescription() { 150 return String.format("%-6d aot %s %s", getId(), JavaMethodInfo.uniqueMethodName(method), 151 getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); 152 } 153 154 private int getId() { 155 return id; 156 } 157 158 private static int getEntryBCI() { 159 return JVMCICompiler.INVOCATION_ENTRY_BCI; 160 } 161 162 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 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 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 } 195 if (obj == null) { 196 return false; 197 } 198 if (getClass() != obj.getClass()) { 199 return false; 200 } 201 AOTCompilationTask other = (AOTCompilationTask) obj; 202 return (this.id == other.id); 203 } 204 205 @Override 206 public int hashCode() { 207 return 31 + id; 208 } 209 210 }