< prev index next >
src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java
Print this page
rev 8632 : 6900757: minor bug fixes to LogCompilation tool
* improve internal error reporting (point to XML element causing trouble)
* fix comparator for sorting by name and start
* make tool more robust wrt. incorrect options and files not found
* make inlining decision output more clear
* adopt uncommon traps history printing
* properly mention compiler in generated logs
* add options for printing time stamps and omitting compilation IDs
* add option for comparing compilation logs
* overall code cleanup and API documentation
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, 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.
@@ -27,45 +27,123 @@
import java.io.PrintStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
+/**
+ * Representation of a compilation scope in a compilation log. This class is a
+ * hybrid: its instances can represent original scopes of methods being
+ * compiled, but are also used to represent call sites in given methods.
+ */
public class CallSite {
+ /**
+ * The index of the call in the caller. This will be 0 if this instance
+ * represents a compilation root.
+ */
private int bci;
+
+ /**
+ * The method that is called at this call site. This will be {@code null}
+ * if this instance represents a compilation root.
+ */
private Method method;
+
+ /**
+ * The invocation count for this call site.
+ */
private int count;
+
+ /**
+ * The receiver type of the call represented by this instance, if known.
+ */
private String receiver;
+
+ /**
+ * In case the {@linkplain receiver receiver type} of the call represented
+ * by this instance is known, this is how often the type was encountered.
+ */
private int receiver_count;
+
+ /**
+ * The reason for a success or failure of an inlining operation at this
+ * call site.
+ */
private String reason;
+
+ /**
+ * A list of all calls in this compilation scope.
+ */
private List<CallSite> calls;
+
+ /**
+ * Number of nodes in the graph at the end of parsing this compilation
+ * scope.
+ */
private int endNodes;
+
+ /**
+ * Number of live nodes in the graph at the end of parsing this compilation
+ * scope.
+ */
private int endLiveNodes;
+
+ /**
+ * Time in seconds since VM startup at which parsing this compilation scope
+ * ended.
+ */
private double timeStamp;
+
+ /**
+ * The inline ID in case the call represented by this instance is inlined,
+ * 0 otherwise.
+ */
private long inlineId;
- CallSite() {
- }
+ /**
+ * List of uncommon traps in this compilation scope.
+ */
+ private List<UncommonTrap> traps;
+ /**
+ * Default constructor: used to create an instance that represents the top
+ * scope of a compilation.
+ */
+ CallSite() {}
+
+ /**
+ * Constructor to create an instance that represents an actual method call.
+ */
CallSite(int bci, Method m) {
this.bci = bci;
this.method = m;
}
+ /**
+ * Add a call site to the compilation scope represented by this instance.
+ */
void add(CallSite site) {
if (getCalls() == null) {
- setCalls(new ArrayList<CallSite>());
+ calls = new ArrayList<>();
}
getCalls().add(site);
}
+ /**
+ * Return the last of the {@linkplain #getCalls() call sites} in this
+ * compilation scope.
+ */
CallSite last() {
- return last(-1);
+ return getCalls().get(getCalls().size() - 1);
}
- CallSite last(int fromEnd) {
- return getCalls().get(getCalls().size() + fromEnd);
+ /**
+ * Return the last-but-one of the {@linkplain #getCalls() call sites} in
+ * this compilation scope.
+ */
+ CallSite lastButOne() {
+ return getCalls().get(getCalls().size() - 2);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (getReason() == null) {
@@ -82,49 +160,45 @@
}
return sb.toString();
}
public void print(PrintStream stream) {
- print(stream, 0);
+ print(stream, 0, true, false);
}
void emit(PrintStream stream, int indent) {
for (int i = 0; i < indent; i++) {
stream.print(' ');
}
}
- private static boolean compat = true;
- public void print(PrintStream stream, int indent) {
+ public void print(PrintStream stream, int indent, boolean printInlining, boolean printUncommonTraps) {
emit(stream, indent);
String m = getMethod().getHolder() + "::" + getMethod().getName();
if (getReason() == null) {
stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)");
-
} else {
- if (isCompat()) {
stream.print(" @ " + getBci() + " " + m + " " + getReason());
- } else {
- stream.print("- @ " + getBci() + " " + m +
- " (" + getMethod().getBytes() + " bytes) " + getReason());
- }
}
stream.printf(" (end time: %6.4f", getTimeStamp());
if (getEndNodes() > 0) {
stream.printf(" nodes: %d live: %d", getEndNodes(), getEndLiveNodes());
}
stream.println(")");
if (getReceiver() != null) {
emit(stream, indent + 4);
- // stream.println("type profile " + method.holder + " -> " + receiver + " (" +
- // receiver_count + "/" + count + "," + (receiver_count * 100 / count) + "%)");
stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" +
(getReceiverCount() * 100 / getCount()) + "%)");
}
- if (getCalls() != null) {
+ if (printInlining && getCalls() != null) {
for (CallSite site : getCalls()) {
+ site.print(stream, indent + 2, printInlining, printUncommonTraps);
+ }
+ }
+ if (printUncommonTraps && getTraps() != null) {
+ for (UncommonTrap site : getTraps()) {
site.print(stream, indent + 2);
}
}
}
@@ -178,20 +252,19 @@
public List<CallSite> getCalls() {
return calls;
}
- public void setCalls(List<CallSite> calls) {
- this.calls = calls;
+ public List<UncommonTrap> getTraps() {
+ return traps;
}
- public static boolean isCompat() {
- return compat;
+ void add(UncommonTrap e) {
+ if (traps == null) {
+ traps = new ArrayList<UncommonTrap>();
}
-
- public static void setCompat(boolean aCompat) {
- compat = aCompat;
+ traps.add(e);
}
void setEndNodes(int n) {
endNodes = n;
}
@@ -214,25 +287,34 @@
public double getTimeStamp() {
return timeStamp;
}
+ /**
+ * Check whether this call site matches another. Every late inline call
+ * site has a unique inline ID. If the call site we're looking for has one,
+ * then use it; otherwise rely on method name and byte code index.
+ */
private boolean matches(CallSite other) {
- // Every late inline call site has a unique inline id. If the
- // call site we're looking for has one then use it other rely
- // on method name and bci.
if (other.inlineId != 0) {
return inlineId == other.inlineId;
}
return method.equals(other.method) && bci == other.bci;
}
+ /**
+ * Locate a late inline call site: find, in this instance's
+ * {@linkplain #calls call sites}, the one furthest down the given call
+ * stack.
+ *
+ * Multiple chains of identical call sites with the same method name / bci
+ * combination are possible, so we have to try them all until we find the
+ * late inline call site that has a matching inline ID.
+ *
+ * @return a matching call site, or {@code null} if none was found.
+ */
public CallSite findCallSite(ArrayDeque<CallSite> sites) {
- // Locate a late inline call site. Multiple chains of
- // identical call sites with the same method name/bci are
- // possible so we have to try them all until we find the late
- // inline call site that has a matching inline id.
if (calls == null) {
return null;
}
CallSite site = sites.pop();
for (CallSite c : calls) {
@@ -251,18 +333,23 @@
}
sites.push(site);
return null;
}
+ /**
+ * Locate a late inline call site in the tree spanned by all this instance's
+ * {@linkplain #calls call sites}, and return the sequence of call sites
+ * (scopes) leading to that late inline call site.
+ */
public ArrayDeque<CallSite> findCallSite2(CallSite site) {
if (calls == null) {
return null;
}
for (CallSite c : calls) {
if (c.matches(site)) {
- ArrayDeque<CallSite> stack = new ArrayDeque<CallSite>();
+ ArrayDeque<CallSite> stack = new ArrayDeque<>();
stack.push(c);
return stack;
} else {
ArrayDeque<CallSite> stack = c.findCallSite2(site);
if (stack != null) {
< prev index next >