1/* 2 * Copyright (c) 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 */ 23package org.graalvm.compiler.core; 24 25import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; 26 27import org.graalvm.compiler.code.CompilationResult; 28import org.graalvm.compiler.core.common.CompilationIdentifier; 29import org.graalvm.compiler.debug.Management; 30import org.graalvm.compiler.debug.TTY; 31import org.graalvm.compiler.options.OptionValues; 32 33import jdk.vm.ci.meta.JavaMethod; 34import jdk.vm.ci.runtime.JVMCICompiler; 35 36/** 37 * Utility for printing an informational line to {@link TTY} upon completion of compiling a method. 38 */ 39public final class CompilationPrinter { 40 41 private final CompilationIdentifier id; 42 private final JavaMethod method; 43 private final int entryBCI; 44 private final long start; 45 private final long allocatedBytesBefore; 46 47 /** 48 * Gets an object that will report statistics for a compilation if 49 * {@link GraalCompilerOptions#PrintCompilation} is enabled and {@link TTY} is not suppressed. 50 * This method should be called just before a compilation starts as it captures pre-compilation 51 * data for the purpose of {@linkplain #finish(CompilationResult) printing} the post-compilation 52 * statistics. 53 * 54 * @param options used to get the value of {@link GraalCompilerOptions#PrintCompilation} 55 * @param id the identifier for the compilation 56 * @param method the method for which code is being compiled 57 * @param entryBCI the BCI at which compilation starts 58 */ 59 public static CompilationPrinter begin(OptionValues options, CompilationIdentifier id, JavaMethod method, int entryBCI) { 60 if (PrintCompilation.getValue(options) && !TTY.isSuppressed()) { 61 try { 62 Class.forName("java.lang.management.ManagementFactory"); 63 } catch (ClassNotFoundException ex) { 64 throw new IllegalArgumentException("PrintCompilation option requires java.management module"); 65 } 66 return new CompilationPrinter(id, method, entryBCI); 67 } 68 return DISABLED; 69 } 70 71 private static final CompilationPrinter DISABLED = new CompilationPrinter(); 72 73 private CompilationPrinter() { 74 this.method = null; 75 this.id = null; 76 this.entryBCI = -1; 77 this.start = -1; 78 this.allocatedBytesBefore = -1; 79 } 80 81 private CompilationPrinter(CompilationIdentifier id, JavaMethod method, int entryBCI) { 82 this.method = method; 83 this.id = id; 84 this.entryBCI = entryBCI; 85 86 final long threadId = Thread.currentThread().getId(); 87 start = System.nanoTime(); 88 allocatedBytesBefore = getAllocatedBytes(threadId); 89 } 90 91 private String getMethodDescription() { 92 return String.format("%-30s %-70s %-45s %-50s %s", id.toString(CompilationIdentifier.Verbosity.ID), 93 method.getDeclaringClass().getName(), method.getName(), 94 method.getSignature().toMethodDescriptor(), 95 entryBCI == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") "); 96 } 97 98 /** 99 * Notifies this object that the compilation finished and the informational line should be 100 * printed to {@link TTY}. 101 */ 102 public void finish(CompilationResult result) { 103 if (id != null) { 104 final long threadId = Thread.currentThread().getId(); 105 final long stop = System.nanoTime(); 106 final long duration = (stop - start) / 1000000; 107 final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1; 108 final int bytecodeSize = result != null ? result.getBytecodeSize() : 0; 109 final long allocatedBytesAfter = getAllocatedBytes(threadId); 110 final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; 111 112 TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); 113 } 114 } 115 116 static com.sun.management.ThreadMXBean threadMXBean; 117 118 static long getAllocatedBytes(long threadId) { 119 if (threadMXBean == null) { 120 threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); 121 } 122 return threadMXBean.getThreadAllocatedBytes(threadId); 123 } 124} 125