| /* |
| * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package jdk.vm.ci.meta; |
| |
| /** |
| * Provides access to the profiling information of one specific method. Every accessor method |
| * returns the information that is available at the time of invocation. If a method is invoked |
| * multiple times, it may return significantly different results for every invocation as the |
| * profiling information may be changed by other Java threads at any time. |
| */ |
| public interface ProfilingInfo { |
| |
| /** |
| * Returns the length of the bytecodes associated with this profile. |
| */ |
| int getCodeSize(); |
| |
| /** |
| * Returns an estimate of how often the branch at the given byte code was taken. |
| * |
| * @return The estimated probability, with 0.0 meaning never and 1.0 meaning always, or -1 if |
| * this information is not available. |
| */ |
| double getBranchTakenProbability(int bci); |
| |
| /** |
| * Returns an estimate of how often the switch cases are taken at the given BCI. The default |
| * case is stored as the last entry. |
| * |
| * @return A double value that contains the estimated probabilities, with 0.0 meaning never and |
| * 1.0 meaning always, or -1 if this information is not available. |
| */ |
| double[] getSwitchProbabilities(int bci); |
| |
| /** |
| * Returns the TypeProfile for the given BCI. |
| * |
| * @return Returns a JavaTypeProfile object, or null if not available. |
| */ |
| JavaTypeProfile getTypeProfile(int bci); |
| |
| /** |
| * Returns the MethodProfile for the given BCI. |
| * |
| * @return Returns a JavaMethodProfile object, or null if not available. |
| */ |
| JavaMethodProfile getMethodProfile(int bci); |
| |
| /** |
| * Returns information if the given BCI did ever throw an exception. |
| * |
| * @return {@link TriState#TRUE} if the instruction has thrown an exception at least once, |
| * {@link TriState#FALSE} if it never threw an exception, and {@link TriState#UNKNOWN} |
| * if this information was not recorded. |
| */ |
| TriState getExceptionSeen(int bci); |
| |
| /** |
| * Returns information if null was ever seen for the given BCI. This information is collected |
| * for the aastore, checkcast and instanceof bytecodes. |
| * |
| * @return {@link TriState#TRUE} if null was seen for the instruction, {@link TriState#FALSE} if |
| * null was NOT seen, and {@link TriState#UNKNOWN} if this information was not recorded. |
| */ |
| TriState getNullSeen(int bci); |
| |
| /** |
| * Returns an estimate how often the current BCI was executed. Avoid comparing execution counts |
| * to each other, as the returned value highly depends on the time of invocation. |
| * |
| * @return the estimated execution count or -1 if not available. |
| */ |
| int getExecutionCount(int bci); |
| |
| /** |
| * Returns how frequently a method was deoptimized for the given deoptimization reason. This |
| * only indicates how often the method did fall back to the interpreter for the execution and |
| * does not indicate how often it was recompiled. |
| * |
| * @param reason the reason for which the number of deoptimizations should be queried |
| * @return the number of times the compiled method deoptimized for the given reason. |
| */ |
| int getDeoptimizationCount(DeoptimizationReason reason); |
| |
| /** |
| * Records the size of the compiler intermediate representation (IR) associated with this |
| * method. |
| * |
| * @param irType the IR type for which the size is being recorded |
| * @param irSize the IR size to be recorded. The unit depends on the IR. |
| * @return whether recording this information for {@code irType} is supported |
| */ |
| boolean setCompilerIRSize(Class<?> irType, int irSize); |
| |
| /** |
| * Gets the size of the compiler intermediate representation (IR) associated with this method |
| * last recorded by {@link #setCompilerIRSize(Class, int)}. |
| * |
| * @param irType the IR type for which the size is being requested |
| * @return the requested IR size or -1 if it is unavailable for {@code irType} |
| */ |
| int getCompilerIRSize(Class<?> irType); |
| |
| /** |
| * Returns true if the profiling information can be assumed as sufficiently accurate. |
| * |
| * @return true if the profiling information was recorded often enough mature enough, false |
| * otherwise. |
| */ |
| boolean isMature(); |
| |
| /** |
| * Force data to be treated as mature if possible. |
| */ |
| void setMature(); |
| |
| /** |
| * Formats this profiling information to a string. |
| * |
| * @param method an optional method that augments the profile string returned |
| * @param sep the separator to use for each separate profile record |
| */ |
| default String toString(ResolvedJavaMethod method, String sep) { |
| StringBuilder buf = new StringBuilder(100); |
| if (method != null) { |
| buf.append(String.format("canBeStaticallyBound: %b%s", method.canBeStaticallyBound(), sep)); |
| } |
| for (int i = 0; i < getCodeSize(); i++) { |
| if (getExecutionCount(i) != -1) { |
| buf.append(String.format("executionCount@%d: %d%s", i, getExecutionCount(i), sep)); |
| } |
| |
| if (getBranchTakenProbability(i) != -1) { |
| buf.append(String.format("branchProbability@%d: %.6f%s", i, getBranchTakenProbability(i), sep)); |
| } |
| |
| double[] switchProbabilities = getSwitchProbabilities(i); |
| if (switchProbabilities != null) { |
| buf.append(String.format("switchProbabilities@%d:", i)); |
| for (int j = 0; j < switchProbabilities.length; j++) { |
| buf.append(String.format(" %.6f", switchProbabilities[j])); |
| } |
| buf.append(sep); |
| } |
| |
| if (getExceptionSeen(i) != TriState.UNKNOWN) { |
| buf.append(String.format("exceptionSeen@%d: %s%s", i, getExceptionSeen(i).name(), sep)); |
| } |
| |
| if (getNullSeen(i) != TriState.UNKNOWN) { |
| buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep)); |
| } |
| |
| JavaTypeProfile typeProfile = getTypeProfile(i); |
| MetaUtil.appendProfile(buf, typeProfile, i, "types", sep); |
| |
| JavaMethodProfile methodProfile = getMethodProfile(i); |
| MetaUtil.appendProfile(buf, methodProfile, i, "methods", sep); |
| } |
| |
| boolean firstDeoptReason = true; |
| for (DeoptimizationReason reason : DeoptimizationReason.values()) { |
| int count = getDeoptimizationCount(reason); |
| if (count > 0) { |
| if (firstDeoptReason) { |
| buf.append("deoptimization history").append(sep); |
| firstDeoptReason = false; |
| } |
| buf.append(String.format(" %s: %d%s", reason.name(), count, sep)); |
| } |
| } |
| if (buf.length() == 0) { |
| return ""; |
| } |
| String s = buf.toString(); |
| return s.substring(0, s.length() - sep.length()); |
| } |
| |
| } |