1 /* 2 * Copyright (c) 2012, 2012, 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 package jdk.internal.jvmci.meta; 24 25 /** 26 * Provides access to the profiling information of one specific method. Every accessor method 27 * returns the information that is available at the time of invocation. If a method is invoked 28 * multiple times, it may return significantly different results for every invocation as the 29 * profiling information may be changed by other Java threads at any time. 30 */ 31 public interface ProfilingInfo { 32 33 /** 34 * Returns the length of the bytecodes associated with this profile. 35 */ 36 int getCodeSize(); 37 38 /** 39 * Returns an estimate of how often the branch at the given byte code was taken. 40 * 41 * @return The estimated probability, with 0.0 meaning never and 1.0 meaning always, or -1 if 42 * this information is not available. 43 */ 44 double getBranchTakenProbability(int bci); 45 46 /** 47 * Returns an estimate of how often the switch cases are taken at the given BCI. The default 48 * case is stored as the last entry. 49 * 50 * @return A double value that contains the estimated probabilities, with 0.0 meaning never and 51 * 1.0 meaning always, or -1 if this information is not available. 52 */ 53 double[] getSwitchProbabilities(int bci); 54 55 /** 56 * Returns the TypeProfile for the given BCI. 57 * 58 * @return Returns a JavaTypeProfile object, or null if not available. 59 */ 60 JavaTypeProfile getTypeProfile(int bci); 61 62 /** 63 * Returns the MethodProfile for the given BCI. 64 * 65 * @return Returns a JavaMethodProfile object, or null if not available. 66 */ 67 JavaMethodProfile getMethodProfile(int bci); 68 69 /** 70 * Returns information if the given BCI did ever throw an exception. 71 * 72 * @return {@link TriState#TRUE} if the instruction has thrown an exception at least once, 73 * {@link TriState#FALSE} if it never threw an exception, and {@link TriState#UNKNOWN} 74 * if this information was not recorded. 75 */ 76 TriState getExceptionSeen(int bci); 77 78 /** 79 * Returns information if null was ever seen for the given BCI. This information is collected 80 * for the aastore, checkcast and instanceof bytecodes. 81 * 82 * @return {@link TriState#TRUE} if null was seen for the instruction, {@link TriState#FALSE} if 83 * null was NOT seen, and {@link TriState#UNKNOWN} if this information was not recorded. 84 */ 85 TriState getNullSeen(int bci); 86 87 /** 88 * Returns an estimate how often the current BCI was executed. Avoid comparing execution counts 89 * to each other, as the returned value highly depends on the time of invocation. 90 * 91 * @return the estimated execution count or -1 if not available. 92 */ 93 int getExecutionCount(int bci); 94 95 /** 96 * Returns how frequently a method was deoptimized for the given deoptimization reason. This 97 * only indicates how often the method did fall back to the interpreter for the execution and 98 * does not indicate how often it was recompiled. 99 * 100 * @param reason the reason for which the number of deoptimizations should be queried 101 * @return the number of times the compiled method deoptimized for the given reason. 102 */ 103 int getDeoptimizationCount(DeoptimizationReason reason); 104 105 /** 106 * Records the size of the compiler intermediate representation (IR) associated with this 107 * method. 108 * 109 * @param irType the IR type for which the size is being recorded 110 * @param irSize the IR size to be recorded. The unit depends on the IR. 111 * @return whether recording this information for {@code irType} is supported 112 */ 113 boolean setCompilerIRSize(Class<?> irType, int irSize); 114 115 /** 116 * Gets the size of the compiler intermediate representation (IR) associated with this method 117 * last recorded by {@link #setCompilerIRSize(Class, int)}. 118 * 119 * @param irType the IR type for which the size is being requested 120 * @return the requested IR size or -1 if it is unavailable for {@code irType} 121 */ 122 int getCompilerIRSize(Class<?> irType); 123 124 /** 125 * Returns true if the profiling information can be assumed as sufficiently accurate. 126 * 127 * @return true if the profiling information was recorded often enough mature enough, false 128 * otherwise. 129 */ 130 boolean isMature(); 131 132 /** 133 * Force data to be treated as mature if possible. 134 */ 135 void setMature(); 136 137 /** 138 * Formats this profiling information to a string. 139 * 140 * @param method an optional method that augments the profile string returned 141 * @param sep the separator to use for each separate profile record 142 */ 143 default String toString(ResolvedJavaMethod method, String sep) { 144 StringBuilder buf = new StringBuilder(100); 145 if (method != null) { 146 buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep)); 147 } 148 for (int i = 0; i < getCodeSize(); i++) { 149 if (getExecutionCount(i) != -1) { 150 buf.append(String.format("executionCount@%d: %d%s", i, getExecutionCount(i), sep)); 151 } 152 153 if (getBranchTakenProbability(i) != -1) { 154 buf.append(String.format("branchProbability@%d: %.6f%s", i, getBranchTakenProbability(i), sep)); 155 } 156 157 double[] switchProbabilities = getSwitchProbabilities(i); 158 if (switchProbabilities != null) { 159 buf.append(String.format("switchProbabilities@%d:", i)); 160 for (int j = 0; j < switchProbabilities.length; j++) { 161 buf.append(String.format(" %.6f", switchProbabilities[j])); 162 } 163 buf.append(sep); 164 } 165 166 if (getExceptionSeen(i) != TriState.UNKNOWN) { 167 buf.append(String.format("exceptionSeen@%d: %s%s", i, getExceptionSeen(i).name(), sep)); 168 } 169 170 if (getNullSeen(i) != TriState.UNKNOWN) { 171 buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep)); 172 } 173 174 JavaTypeProfile typeProfile = getTypeProfile(i); 175 MetaUtil.appendProfile(buf, typeProfile, i, "types", sep); 176 177 JavaMethodProfile methodProfile = getMethodProfile(i); 178 MetaUtil.appendProfile(buf, methodProfile, i, "methods", sep); 179 } 180 181 boolean firstDeoptReason = true; 182 for (DeoptimizationReason reason : DeoptimizationReason.values()) { 183 int count = getDeoptimizationCount(reason); 184 if (count > 0) { 185 if (firstDeoptReason) { 186 buf.append("deoptimization history").append(sep); 187 firstDeoptReason = false; 188 } 189 buf.append(String.format(" %s: %d%s", reason.name(), count, sep)); 190 } 191 } 192 if (buf.length() == 0) { 193 return ""; 194 } 195 String s = buf.toString(); 196 return s.substring(0, s.length() - sep.length()); 197 } 198 199 }