< prev index next >
src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.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
*** 31,64 ****
import java.io.FileReader;
import java.io.PrintStream;
import java.io.Reader;
import java.util.ArrayDeque;
import java.util.ArrayList;
- import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
! import java.util.Stack;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
! public class LogParser extends DefaultHandler implements ErrorHandler, Constants {
- static final HashMap<String, String> typeMap;
static {
! typeMap = new HashMap<String, String>();
! typeMap.put("[I", "int[]");
! typeMap.put("[C", "char[]");
! typeMap.put("[Z", "boolean[]");
! typeMap.put("[L", "Object[]");
! typeMap.put("[B", "byte[]");
! }
static Comparator<LogEvent> sortByStart = new Comparator<LogEvent>() {
public int compare(LogEvent a, LogEvent b) {
double difference = (a.getStart() - b.getStart());
if (difference < 0) {
--- 31,303 ----
import java.io.FileReader;
import java.io.PrintStream;
import java.io.Reader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
+ import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
! import java.util.regex.Pattern;
!
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
+ import org.xml.sax.Locator;
import org.xml.sax.helpers.DefaultHandler;
! /**
! * A SAX parser for HotSpot compilation logs. The bulk of the parsing and event
! * maintenance work is done in the {@link #startElement(String,String,String,Attributes)}
! * and {@link #endElement(String,String,String)} methods.
! */
! public class LogParser extends DefaultHandler implements ErrorHandler {
!
! static final Pattern spacePattern = Pattern.compile(" ");
!
! /**
! * Map internal array type descriptors to Java names.
! */
! static final HashMap<String, String> type2printableMap;
!
! /**
! * Map Java primitive type names to internal type descriptors.
! */
! static final HashMap<String, String> type2vmtypeMap;
static {
! type2printableMap = new HashMap<>();
! type2printableMap.put("[I", "int[]");
! type2printableMap.put("[C", "char[]");
! type2printableMap.put("[Z", "boolean[]");
! type2printableMap.put("[L", "Object[]");
! type2printableMap.put("[B", "byte[]");
!
! type2vmtypeMap = new HashMap<>();
! type2vmtypeMap.put("void", "V");
! type2vmtypeMap.put("boolean", "Z");
! type2vmtypeMap.put("byte", "B");
! type2vmtypeMap.put("char", "C");
! type2vmtypeMap.put("short", "S");
! type2vmtypeMap.put("int", "I");
! type2vmtypeMap.put("long", "J");
! type2vmtypeMap.put("float", "F");
! type2vmtypeMap.put("double", "D");
! }
!
! static String[] bytecodes = new String[] {
! "nop",
! "aconst_null",
! "iconst_m1",
! "iconst_0",
! "iconst_1",
! "iconst_2",
! "iconst_3",
! "iconst_4",
! "iconst_5",
! "lconst_0",
! "lconst_1",
! "fconst_0",
! "fconst_1",
! "fconst_2",
! "dconst_0",
! "dconst_1",
! "bipush",
! "sipush",
! "ldc",
! "ldc_w",
! "ldc2_w",
! "iload",
! "lload",
! "fload",
! "dload",
! "aload",
! "iload_0",
! "iload_1",
! "iload_2",
! "iload_3",
! "lload_0",
! "lload_1",
! "lload_2",
! "lload_3",
! "fload_0",
! "fload_1",
! "fload_2",
! "fload_3",
! "dload_0",
! "dload_1",
! "dload_2",
! "dload_3",
! "aload_0",
! "aload_1",
! "aload_2",
! "aload_3",
! "iaload",
! "laload",
! "faload",
! "daload",
! "aaload",
! "baload",
! "caload",
! "saload",
! "istore",
! "lstore",
! "fstore",
! "dstore",
! "astore",
! "istore_0",
! "istore_1",
! "istore_2",
! "istore_3",
! "lstore_0",
! "lstore_1",
! "lstore_2",
! "lstore_3",
! "fstore_0",
! "fstore_1",
! "fstore_2",
! "fstore_3",
! "dstore_0",
! "dstore_1",
! "dstore_2",
! "dstore_3",
! "astore_0",
! "astore_1",
! "astore_2",
! "astore_3",
! "iastore",
! "lastore",
! "fastore",
! "dastore",
! "aastore",
! "bastore",
! "castore",
! "sastore",
! "pop",
! "pop2",
! "dup",
! "dup_x1",
! "dup_x2",
! "dup2",
! "dup2_x1",
! "dup2_x2",
! "swap",
! "iadd",
! "ladd",
! "fadd",
! "dadd",
! "isub",
! "lsub",
! "fsub",
! "dsub",
! "imul",
! "lmul",
! "fmul",
! "dmul",
! "idiv",
! "ldiv",
! "fdiv",
! "ddiv",
! "irem",
! "lrem",
! "frem",
! "drem",
! "ineg",
! "lneg",
! "fneg",
! "dneg",
! "ishl",
! "lshl",
! "ishr",
! "lshr",
! "iushr",
! "lushr",
! "iand",
! "land",
! "ior",
! "lor",
! "ixor",
! "lxor",
! "iinc",
! "i2l",
! "i2f",
! "i2d",
! "l2i",
! "l2f",
! "l2d",
! "f2i",
! "f2l",
! "f2d",
! "d2i",
! "d2l",
! "d2f",
! "i2b",
! "i2c",
! "i2s",
! "lcmp",
! "fcmpl",
! "fcmpg",
! "dcmpl",
! "dcmpg",
! "ifeq",
! "ifne",
! "iflt",
! "ifge",
! "ifgt",
! "ifle",
! "if_icmpeq",
! "if_icmpne",
! "if_icmplt",
! "if_icmpge",
! "if_icmpgt",
! "if_icmple",
! "if_acmpeq",
! "if_acmpne",
! "goto",
! "jsr",
! "ret",
! "tableswitch",
! "lookupswitch",
! "ireturn",
! "lreturn",
! "freturn",
! "dreturn",
! "areturn",
! "return",
! "getstatic",
! "putstatic",
! "getfield",
! "putfield",
! "invokevirtual",
! "invokespecial",
! "invokestatic",
! "invokeinterface",
! "invokedynamic",
! "new",
! "newarray",
! "anewarray",
! "arraylength",
! "athrow",
! "checkcast",
! "instanceof",
! "monitorenter",
! "monitorexit",
! "wide",
! "multianewarray",
! "ifnull",
! "ifnonnull",
! "goto_w",
! "jsr_w",
! "breakpoint"
! };
+ /**
+ * Sort log events by start time.
+ */
static Comparator<LogEvent> sortByStart = new Comparator<LogEvent>() {
public int compare(LogEvent a, LogEvent b) {
double difference = (a.getStart() - b.getStart());
if (difference < 0) {
*** 78,106 ****
@Override
public int hashCode() {
return 7;
}
};
static Comparator<LogEvent> sortByNameAndStart = new Comparator<LogEvent>() {
public int compare(LogEvent a, LogEvent b) {
Compilation c1 = a.getCompilation();
Compilation c2 = b.getCompilation();
! if (c1 != null && c2 != null) {
int result = c1.getMethod().toString().compareTo(c2.getMethod().toString());
if (result != 0) {
return result;
}
! }
! double difference = (a.getStart() - b.getStart());
! if (difference < 0) {
return -1;
! }
! if (difference > 0) {
return 1;
}
! return 0;
}
public boolean equals(Object other) {
return false;
}
--- 317,349 ----
@Override
public int hashCode() {
return 7;
}
};
+
+ /**
+ * Sort log events first by the name of the compiled method, then by start
+ * time. In case one of the events has no associated compilation (or the
+ * associated compilation has no method name), the event with a compilation
+ * and/or name is considered the larger one.
+ */
static Comparator<LogEvent> sortByNameAndStart = new Comparator<LogEvent>() {
public int compare(LogEvent a, LogEvent b) {
Compilation c1 = a.getCompilation();
Compilation c2 = b.getCompilation();
! if (c1 != null && c1.getMethod() != null && c2 != null && c2.getMethod() != null) {
int result = c1.getMethod().toString().compareTo(c2.getMethod().toString());
if (result != 0) {
return result;
}
! } else if ((c1 == null || c1.getMethod() == null) && c2 != null && c2.getMethod() != null) {
return -1;
! } else if ((c2 == null || c2.getMethod() == null) && c1 != null && c1.getMethod() != null) {
return 1;
}
! return Double.compare(a.getStart(), b.getStart());
}
public boolean equals(Object other) {
return false;
}
*** 108,117 ****
--- 351,364 ----
@Override
public int hashCode() {
return 7;
}
};
+
+ /**
+ * Sort log events by duration.
+ */
static Comparator<LogEvent> sortByElapsed = new Comparator<LogEvent>() {
public int compare(LogEvent a, LogEvent b) {
double difference = (a.getElapsedTime() - b.getElapsedTime());
if (difference < 0) {
*** 132,141 ****
--- 379,392 ----
public int hashCode() {
return 7;
}
};
+ /**
+ * Shrink-wrapped representation of a JVMState (tailored to meet this
+ * tool's needs). It only records a method and bytecode instruction index.
+ */
class Jvms {
Jvms(Method method, int bci) {
this.method = method;
this.bci = bci;
}
*** 144,198 ****
final public String toString() {
return "@" + bci + " " + method;
}
}
class LockElimination extends BasicLogEvent {
! ArrayList<Jvms> jvms = new ArrayList<Jvms>(1);
final String kind;
final String classId;
final String tagName;
LockElimination(String tagName, double start, String id, String kind, String classId) {
super(start, id);
this.kind = kind;
this.classId = classId;
this.tagName = tagName;
}
@Override
! public void print(PrintStream stream) {
! stream.printf("%s %s %s %s %.3f ", getId(), tagName, kind, classId, getStart());
stream.print(jvms.toString());
stream.print("\n");
}
void addJVMS(Method method, int bci) {
jvms.add(new Jvms(method, bci));
}
}
! private ArrayList<LogEvent> events = new ArrayList<LogEvent>();
!
! private HashMap<String, String> types = new HashMap<String, String>();
! private HashMap<String, Method> methods = new HashMap<String, Method>();
! private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<String, NMethod>();
! private HashMap<String, Compilation> compiles = new HashMap<String, Compilation>();
private String failureReason;
! private int bci;
! private Stack<CallSite> scopes = new Stack<CallSite>();
private Compilation compile;
private CallSite site;
private CallSite methodHandleSite;
! private Stack<Phase> phaseStack = new Stack<Phase>();
private LockElimination currentLockElimination;
private UncommonTrapEvent currentTrap;
! private Stack<CallSite> lateInlineScope;
private boolean lateInlining;
long parseLong(String l) {
try {
return Long.decode(l).longValue();
} catch (NumberFormatException nfe) {
int split = l.length() - 8;
--- 395,602 ----
final public String toString() {
return "@" + bci + " " + method;
}
}
+ /**
+ * Representation of a lock elimination. Locks, corresponding to
+ * synchronized blocks and method calls, may be eliminated if the object in
+ * question is guaranteed to be used thread-locally.
+ */
class LockElimination extends BasicLogEvent {
! /**
! * Track all locations from which this lock was eliminated.
! */
! ArrayList<Jvms> jvms = new ArrayList<>(1);
!
! /**
! * The kind of lock (coarsened, nested, non-escaping, unknown).
! */
final String kind;
+
+ /**
+ * The lock class (unlock, lock, unknown).
+ */
final String classId;
+
+ /**
+ * The precise type of lock.
+ */
final String tagName;
+
LockElimination(String tagName, double start, String id, String kind, String classId) {
super(start, id);
this.kind = kind;
this.classId = classId;
this.tagName = tagName;
}
@Override
! public void print(PrintStream stream, boolean printID) {
! if (printID) {
! stream.printf("%s ", getId());
! }
! stream.printf("%s %s %s %.3f ", tagName, kind, classId, getStart());
stream.print(jvms.toString());
stream.print("\n");
}
void addJVMS(Method method, int bci) {
jvms.add(new Jvms(method, bci));
}
}
! /**
! * A list of log events. This is populated with the events found in the
! * compilation log file during parsing.
! */
! private ArrayList<LogEvent> events = new ArrayList<>();
!
! /**
! * Map compilation log IDs to type names.
! */
! private HashMap<String, String> types = new HashMap<>();
!
! /**
! * Map compilation log IDs to methods.
! */
! private HashMap<String, Method> methods = new HashMap<>();
!
! /**
! * Map compilation IDs ({@see #makeId()}) to newly created nmethods.
! */
! private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<>();
!
! /**
! * Map compilation task IDs {@see #makeId()}) to {@link Compilation}
! * objects.
! */
! private HashMap<String, Compilation> compiles = new HashMap<>();
!
! /**
! * Track compilation failure reasons.
! */
private String failureReason;
!
! /**
! * The current bytecode instruction index.
! */
! private int current_bci;
!
! /**
! * The current bytecode instruction.
! */
! private int current_bytecode;
!
! /**
! * A sequence of {@link CallSite}s representing a call stack. A scope
! * typically holds several {@link CallSite}s that represent calls
! * originating from that scope.
! *
! * New scopes are typically pushed when parse log events are encountered
! * ({@see #startElement()}) and popped when parsing of a given Java method
! * is done ({@see #endElement()}). Parsing events can be nested. Several
! * other events add information to scopes ({@see #startElement()}).
! */
! private Deque<CallSite> scopes = new ArrayDeque<>();
!
! /**
! * The current compilation.
! */
private Compilation compile;
+
+ /**
+ * The {@linkplain CallSite compilation scope} currently in focus.
+ */
private CallSite site;
+
+ /**
+ * The {@linkplain CallSite method handle call site} currently under
+ * observation.
+ */
private CallSite methodHandleSite;
!
! /**
! * Keep track of potentially nested compiler {@linkplain Phase phases}.
! */
! private Deque<Phase> phaseStack = new ArrayDeque<>();
!
! /**
! * The {@linkplain LockElimination lock elimination event} currently being
! * processed.
! */
private LockElimination currentLockElimination;
+
+ /**
+ * The {@linkplain UncommonTrapEvent uncommon trap event} currently being
+ * processed.
+ */
private UncommonTrapEvent currentTrap;
!
! /**
! * During the processing of a late inline event, this stack holds the
! * {@link CallSite}s that represent the inlining event's call stack.
! */
! private Deque<CallSite> lateInlineScope;
!
! /**
! * Denote whether a late inlining event is currently being processed.
! */
private boolean lateInlining;
+ /**
+ * A document locator to provide better error messages: this allows the
+ * tool to display in which line of the log file the problem occurred.
+ */
+ private Locator locator;
+
+ /**
+ * Callback for the SAX framework to set the document locator.
+ */
+ @Override
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+ /**
+ * Report an internal error explicitly raised, i.e., not derived from an
+ * exception.
+ *
+ * @param msg The error message to report.
+ */
+ private void reportInternalError(String msg) {
+ reportInternalError(msg, null);
+ }
+
+ /**
+ * Report an internal error derived from an exception.
+ *
+ * @param msg The beginning of the error message to report. The message
+ * from the exception will be appended to this.
+ * @param e The exception that led to the internal error.
+ */
+ private void reportInternalError(String msg, Exception e) {
+ if (locator != null) {
+ msg += " at " + locator.getLineNumber() + ":" + locator.getColumnNumber();
+ if (e != null) {
+ msg += " - " + e.getMessage();
+ }
+ }
+ if (e != null) {
+ throw new Error(msg, e);
+ } else {
+ throw new Error(msg);
+ }
+ }
+
+ /**
+ * Parse a long hexadecimal address into a {@code long} value. As Java only
+ * supports positive {@code long} values, extra error handling and parsing
+ * logic is provided.
+ */
long parseLong(String l) {
try {
return Long.decode(l).longValue();
} catch (NumberFormatException nfe) {
int split = l.length() - 8;
*** 205,224 ****
System.out.println(s1);
System.out.println(s2);
System.out.println(v1);
System.out.println(v2);
System.out.println(Long.toHexString(v1 + v2));
! throw new InternalError("bad conversion");
}
return v1 + v2;
}
}
public static ArrayList<LogEvent> parse(String file, boolean cleanup) throws Exception {
return parse(new FileReader(file), cleanup);
}
public static ArrayList<LogEvent> parse(Reader reader, boolean cleanup) throws Exception {
// Create the XML input factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// Create the XML LogEvent reader
--- 609,641 ----
System.out.println(s1);
System.out.println(s2);
System.out.println(v1);
System.out.println(v2);
System.out.println(Long.toHexString(v1 + v2));
! reportInternalError("bad conversion");
}
return v1 + v2;
}
}
+ /**
+ * Entry point for log file parsing with a file name.
+ *
+ * @param file The name of the log file to parse.
+ * @param cleanup Whether to perform bad XML cleanup during parsing (this
+ * is relevant for some log files generated by the 1.5 JVM).
+ * @return a list of {@link LogEvent} instances describing the events found
+ * in the log file.
+ */
public static ArrayList<LogEvent> parse(String file, boolean cleanup) throws Exception {
return parse(new FileReader(file), cleanup);
}
+ /**
+ * Entry point for log file parsing with a file reader.
+ * {@see #parse(String,boolean)}
+ */
public static ArrayList<LogEvent> parse(Reader reader, boolean cleanup) throws Exception {
// Create the XML input factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// Create the XML LogEvent reader
*** 236,318 ****
} catch (Throwable th) {
th.printStackTrace();
// Carry on with what we've got...
}
! // Associate compilations with their NMethods
! for (NMethod nm : log.nmethods.values()) {
! Compilation c = log.compiles.get(nm.getId());
! nm.setCompilation(c);
! // Native wrappers for methods don't have a compilation
! if (c != null) {
! c.setNMethod(nm);
}
}
-
- // Initially we want the LogEvent log sorted by timestamp
- Collections.sort(log.events, sortByStart);
return log.events;
}
String search(Attributes attr, String name) {
String result = attr.getValue(name);
if (result != null) {
return result;
} else {
! throw new InternalError("can't find " + name);
}
}
String search(Attributes attr, String name, String defaultValue) {
String result = attr.getValue(name);
if (result != null) {
return result;
}
return defaultValue;
}
- int indent = 0;
String type(String id) {
String result = types.get(id);
if (result == null) {
! throw new InternalError(id);
}
! String remapped = typeMap.get(result);
if (remapped != null) {
return remapped;
}
return result;
}
void type(String id, String name) {
assert type(id) == null;
types.put(id, name);
}
Method method(String id) {
Method result = methods.get(id);
if (result == null) {
! throw new InternalError(id);
}
return result;
}
public String makeId(Attributes atts) {
String id = atts.getValue("compile_id");
String kind = atts.getValue("kind");
if (kind != null && kind.equals("osr")) {
id += "%";
}
return id;
}
@Override
! public void startElement(String uri,
! String localName,
! String qname,
! Attributes atts) {
if (qname.equals("phase")) {
Phase p = new Phase(search(atts, "name"),
Double.parseDouble(search(atts, "stamp")),
Integer.parseInt(search(atts, "nodes", "0")),
Integer.parseInt(search(atts, "live", "0")));
--- 653,848 ----
} catch (Throwable th) {
th.printStackTrace();
// Carry on with what we've got...
}
! // Associate compilations with their NMethods and other kinds of events
! for (LogEvent e : log.events) {
! if (e instanceof BasicLogEvent) {
! BasicLogEvent ble = (BasicLogEvent) e;
! Compilation c = log.compiles.get(ble.getId());
! if (c == null) {
! if (!(ble instanceof NMethod)) {
! throw new InternalError("only nmethods should have a null compilation, here's a " + ble.getClass());
! }
! continue;
! }
! ble.setCompilation(c);
! if (ble instanceof NMethod) {
! c.setNMethod((NMethod) ble);
! }
}
}
return log.events;
}
+ /**
+ * Retrieve a given attribute's value from a collection of XML tag
+ * attributes. Report an error if the requested attribute is not found.
+ *
+ * @param attr A collection of XML tag attributes.
+ * @param name The name of the attribute the value of which is to be found.
+ * @return The value of the requested attribute, or {@code null} if it was
+ * not found.
+ */
String search(Attributes attr, String name) {
String result = attr.getValue(name);
if (result != null) {
return result;
} else {
! reportInternalError("can't find " + name);
! return null;
}
}
+ /**
+ * Retrieve a given attribute's value from a collection of XML tag
+ * attributes. Return a default value if the requested attribute is not
+ * found.
+ *
+ * @param attr A collection of XML tag attributes.
+ * @param name The name of the attribute the value of which is to be found.
+ * @param defaultValue The default value to return if the attribute is not
+ * found.
+ * @return The value of the requested attribute, or the default value if it
+ * was not found.
+ */
String search(Attributes attr, String name, String defaultValue) {
String result = attr.getValue(name);
if (result != null) {
return result;
}
return defaultValue;
}
+ /**
+ * Map a type ID from the compilation log to an actual type name. In case
+ * the type represents an internal array type descriptor, return a
+ * Java-level name. If the type ID cannot be mapped to a name, raise an
+ * error.
+ */
String type(String id) {
String result = types.get(id);
if (result == null) {
! reportInternalError(id);
}
! String remapped = type2printableMap.get(result);
if (remapped != null) {
return remapped;
}
return result;
}
+ /**
+ * Register a mapping from log file type ID to type name.
+ */
void type(String id, String name) {
assert type(id) == null;
types.put(id, name);
}
+ /**
+ * Map a log file type ID to an internal type declarator.
+ */
+ String sigtype(String id) {
+ String result = types.get(id);
+ String remapped = type2vmtypeMap.get(result);
+ if (remapped != null) {
+ return remapped;
+ }
+ if (result == null) {
+ reportInternalError(id);
+ }
+ if (result.charAt(0) == '[') {
+ return result;
+ }
+ return "L" + result + ";";
+ }
+
+ /**
+ * Retrieve a method based on the log file ID it was registered under.
+ * Raise an error if the ID does not map to a method.
+ */
Method method(String id) {
Method result = methods.get(id);
if (result == null) {
! reportInternalError(id);
}
return result;
}
+ /**
+ * From a compilation ID and kind, assemble a compilation ID for inclusion
+ * in the output.
+ *
+ * @param atts A collection of XML attributes from which the required
+ * attributes are retrieved.
+ */
public String makeId(Attributes atts) {
String id = atts.getValue("compile_id");
String kind = atts.getValue("kind");
if (kind != null && kind.equals("osr")) {
id += "%";
}
return id;
}
+ /**
+ * Process the start of a compilation log XML element.<ul>
+ * <li><b>phase:</b> record the beginning of a compilation phase, pushing
+ * it on the {@linkplain #phaseStack phase stack} and collecting
+ * information about the compiler graph.</li>
+ * <li><b>phase_done:</b> record the end of a compilation phase, popping it
+ * off the {@linkplain #phaseStack phase stack} and collecting information
+ * about the compiler graph (number of nodes and live nodes).</li>
+ * <li><b>task:</b> register the start of a new compilation.</li>
+ * <li><b>type:</b> register a type.</li>
+ * <li><b>bc:</b> note the current bytecode index and instruction name,
+ * updating {@link #current_bci} and {@link #current_bytecode}.</li>
+ * <li><b>klass:</b> register a type (class).</li>
+ * <li><b>method:</b> register a Java method.</li>
+ * <li><b>call:</b> process a call, populating {@link #site} with the
+ * appropriate data.</li>
+ * <li><b>regalloc:</b> record the register allocator's trip count in the
+ * {@linkplain #compile current compilation}.</li>
+ * <li><b>inline_fail:</b> record the reason for a failed inline
+ * operation.</li>
+ * <li><b>inline_success:</b> record a successful inlining operation,
+ * noting the success reason in the {@linkplain #site call site}.</li>
+ * <li><b>failure:</b> note a compilation failure, storing the reason
+ * description in {@link #failureReason}.</li>
+ * <li><b>task_done:</b> register the end of a compilation, recording time
+ * stamp and success information.</li>
+ * <li><b>make_not_entrant:</b> deal with making a native method
+ * non-callable (e.g., during an OSR compilation, if there are still
+ * activations) or a zombie (when the method can be deleted).</li>
+ * <li><b>uncommon_trap:</b> process an uncommon trap, setting the
+ * {@link #currentTrap} field.</li>
+ * <li><b>eliminate_lock:</b> record the start of a lock elimination,
+ * setting the {@link #currentLockElimination} event.</li>
+ * <li><b>late_inline:</b> start processing a late inline decision:
+ * initialize the {@linkplain #lateInlineScope inline scope stack}, create
+ * an {@linkplain #site initial scope} with a bogus bytecode index and the
+ * right inline ID, and push the scope with the inline ID attached. Note
+ * that most of late inlining processing happens in
+ * {@link #endElement()}.</li>
+ * <li><b>jvms:</b> record a {@linkplain Jvms JVMState}. Depending on the
+ * context in which this event is encountered, this can mean adding
+ * information to the currently being processed trap, lock elimination, or
+ * inlining operation.</li>
+ * <li><b>inline_id:</b> set the inline ID in the
+ * {@linkplain #site current call site}.</li>
+ * <li><b>nmethod:</b> record the creation of a new {@link NMethod} and
+ * store it in the {@link #nmethods} map.</li>
+ * <li><b>parse:</b> begin parsing a Java method's bytecode and
+ * transforming it into an initial compiler IR graph.</li>
+ * <li><b>parse_done:</b> finish parsing a Java method's bytecode.</li>
+ * </ul>
+ */
@Override
! public void startElement(String uri, String localName, String qname, Attributes atts) {
if (qname.equals("phase")) {
Phase p = new Phase(search(atts, "name"),
Double.parseDouble(search(atts, "stamp")),
Integer.parseInt(search(atts, "nodes", "0")),
Integer.parseInt(search(atts, "live", "0")));
*** 320,377 ****
} else if (qname.equals("phase_done")) {
Phase p = phaseStack.pop();
String phaseName = search(atts, "name", null);
if (phaseName != null && !p.getId().equals(phaseName)) {
System.out.println("phase: " + p.getId());
! throw new InternalError("phase name mismatch");
}
p.setEnd(Double.parseDouble(search(atts, "stamp")));
p.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
p.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
compile.getPhases().add(p);
} else if (qname.equals("task")) {
compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1")));
compile.setStart(Double.parseDouble(search(atts, "stamp")));
compile.setICount(search(atts, "count", "0"));
compile.setBCount(search(atts, "backedge_count", "0"));
!
! String method = atts.getValue("method");
! int space = method.indexOf(' ');
! method = method.substring(0, space) + "::" +
! method.substring(space + 1, method.indexOf(' ', space + 1) + 1);
String compiler = atts.getValue("compiler");
if (compiler == null) {
compiler = "";
}
String kind = atts.getValue("compile_kind");
if (kind == null) {
kind = "normal";
}
if (kind.equals("osr")) {
compile.setOsr(true);
- compile.setOsr_bci(Integer.parseInt(search(atts, "osr_bci")));
} else if (kind.equals("c2i")) {
! compile.setSpecial("--- adapter " + method);
} else {
! compile.setSpecial(compile.getId() + " " + method + " (0 bytes)");
}
events.add(compile);
! compiles.put(makeId(atts), compile);
site = compile.getCall();
} else if (qname.equals("type")) {
type(search(atts, "id"), search(atts, "name"));
} else if (qname.equals("bc")) {
! bci = Integer.parseInt(search(atts, "bci"));
} else if (qname.equals("klass")) {
type(search(atts, "id"), search(atts, "name"));
} else if (qname.equals("method")) {
String id = search(atts, "id");
Method m = new Method();
m.setHolder(type(search(atts, "holder")));
m.setName(search(atts, "name"));
m.setReturnType(type(search(atts, "return")));
! m.setArguments(search(atts, "arguments", "void"));
if (search(atts, "unloaded", "0").equals("0")) {
m.setBytes(search(atts, "bytes"));
m.setIICount(search(atts, "iicount"));
m.setFlags(search(atts, "flags"));
--- 850,936 ----
} else if (qname.equals("phase_done")) {
Phase p = phaseStack.pop();
String phaseName = search(atts, "name", null);
if (phaseName != null && !p.getId().equals(phaseName)) {
System.out.println("phase: " + p.getId());
! reportInternalError("phase name mismatch");
}
p.setEnd(Double.parseDouble(search(atts, "stamp")));
p.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
p.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
compile.getPhases().add(p);
} else if (qname.equals("task")) {
+ String id = makeId(atts);
+
+ // Create the new Compilation instance and populate it with readily
+ // available data.
compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1")));
compile.setStart(Double.parseDouble(search(atts, "stamp")));
compile.setICount(search(atts, "count", "0"));
compile.setBCount(search(atts, "backedge_count", "0"));
! compile.setBCI(Integer.parseInt(search(atts, "osr_bci", "-1")));
String compiler = atts.getValue("compiler");
if (compiler == null) {
compiler = "";
}
+ compile.setCompiler(compiler);
+
+ // Extract the name of the compiled method.
+ String[] parts = spacePattern.split(atts.getValue("method"));
+ String methodName = parts[0] + "::" + parts[1];
+
+ // Continue collecting compilation meta-data.
String kind = atts.getValue("compile_kind");
if (kind == null) {
kind = "normal";
}
if (kind.equals("osr")) {
compile.setOsr(true);
} else if (kind.equals("c2i")) {
! compile.setSpecial("--- adapter " + methodName);
} else {
! compile.setSpecial(compile.getId() + " " + methodName + " (0 bytes)");
}
+
+ // Build a dummy method to stuff in the Compilation at the
+ // beginning.
+ Method m = new Method();
+ m.setHolder(parts[0]);
+ m.setName(parts[1]);
+ m.setSignature(parts[2]);
+ m.setFlags("0");
+ m.setBytes("unknown");
+ compile.setMethod(m);
events.add(compile);
! compiles.put(id, compile);
site = compile.getCall();
} else if (qname.equals("type")) {
type(search(atts, "id"), search(atts, "name"));
} else if (qname.equals("bc")) {
! current_bci = Integer.parseInt(search(atts, "bci"));
! current_bytecode = Integer.parseInt(search(atts, "code"));
} else if (qname.equals("klass")) {
type(search(atts, "id"), search(atts, "name"));
} else if (qname.equals("method")) {
String id = search(atts, "id");
Method m = new Method();
m.setHolder(type(search(atts, "holder")));
m.setName(search(atts, "name"));
m.setReturnType(type(search(atts, "return")));
! String arguments = atts.getValue("arguments");;
! if (arguments == null) {
! m.setSignature("()" + sigtype(atts.getValue("return")));
! } else {
! String[] args = spacePattern.split(arguments);
! StringBuilder sb = new StringBuilder("(");
! for (int i = 0; i < args.length; i++) {
! sb.append(sigtype(args[i]));
! }
! sb.append(")");
! sb.append(sigtype(atts.getValue("return")));
! m.setSignature(sb.toString());
! }
if (search(atts, "unloaded", "0").equals("0")) {
m.setBytes(search(atts, "bytes"));
m.setIICount(search(atts, "iicount"));
m.setFlags(search(atts, "flags"));
*** 383,411 ****
}
Method m = method(search(atts, "method"));
if (lateInlining && scopes.size() == 0) {
// re-attempting already seen call site (late inlining for MH invokes)
if (m != site.getMethod()) {
! if (bci != site.getBci()) {
! System.out.println(m + " bci: " + bci);
! System.out.println(site.getMethod() + " bci: " + site.getBci());
! throw new InternalError("bci mismatch after late inlining");
}
site.setMethod(m);
}
} else {
! site = new CallSite(bci, m);
}
site.setCount(Integer.parseInt(search(atts, "count", "0")));
String receiver = atts.getValue("receiver");
if (receiver != null) {
site.setReceiver(type(receiver));
site.setReceiver_count(Integer.parseInt(search(atts, "receiver_count")));
}
int methodHandle = Integer.parseInt(search(atts, "method_handle_intrinsic", "0"));
if (lateInlining && scopes.size() == 0) {
! // The call was added before this round of late inlining
} else if (methodHandle == 0) {
scopes.peek().add(site);
} else {
// method handle call site can be followed by another
// call (in case it is inlined). If that happens we
--- 942,973 ----
}
Method m = method(search(atts, "method"));
if (lateInlining && scopes.size() == 0) {
// re-attempting already seen call site (late inlining for MH invokes)
if (m != site.getMethod()) {
! if (current_bci != site.getBci()) {
! System.err.println(m + " bci: " + current_bci);
! System.err.println(site.getMethod() + " bci: " + site.getBci());
! reportInternalError("bci mismatch after late inlining");
}
site.setMethod(m);
}
} else {
! // We're dealing with a new call site; the called method is
! // likely to be parsed next.
! site = new CallSite(current_bci, m);
}
site.setCount(Integer.parseInt(search(atts, "count", "0")));
String receiver = atts.getValue("receiver");
if (receiver != null) {
site.setReceiver(type(receiver));
site.setReceiver_count(Integer.parseInt(search(atts, "receiver_count")));
}
int methodHandle = Integer.parseInt(search(atts, "method_handle_intrinsic", "0"));
if (lateInlining && scopes.size() == 0) {
! // The call was already added before this round of late
! // inlining. Ignore.
} else if (methodHandle == 0) {
scopes.peek().add(site);
} else {
// method handle call site can be followed by another
// call (in case it is inlined). If that happens we
*** 419,440 ****
if (methodHandleSite != null) {
scopes.peek().add(methodHandleSite);
methodHandleSite = null;
}
if (lateInlining && scopes.size() == 0) {
! site.setReason(search(atts, "reason"));
lateInlining = false;
} else {
! scopes.peek().last().setReason(search(atts, "reason"));
}
} else if (qname.equals("inline_success")) {
if (methodHandleSite != null) {
! throw new InternalError("method handle site should have been replaced");
! }
! if (lateInlining && scopes.size() == 0) {
! site.setReason(null);
}
} else if (qname.equals("failure")) {
failureReason = search(atts, "reason");
} else if (qname.equals("task_done")) {
compile.setEnd(Double.parseDouble(search(atts, "stamp")));
if (Integer.parseInt(search(atts, "success")) == 0) {
--- 981,1000 ----
if (methodHandleSite != null) {
scopes.peek().add(methodHandleSite);
methodHandleSite = null;
}
if (lateInlining && scopes.size() == 0) {
! site.setReason("fail: " + search(atts, "reason"));
lateInlining = false;
} else {
! scopes.peek().last().setReason("fail: " + search(atts, "reason"));
}
} else if (qname.equals("inline_success")) {
if (methodHandleSite != null) {
! reportInternalError("method handle site should have been replaced");
}
+ site.setReason("succeed: " + search(atts, "reason"));
} else if (qname.equals("failure")) {
failureReason = search(atts, "reason");
} else if (qname.equals("task_done")) {
compile.setEnd(Double.parseDouble(search(atts, "stamp")));
if (Integer.parseInt(search(atts, "success")) == 0) {
*** 442,452 ****
failureReason = null;
}
} else if (qname.equals("make_not_entrant")) {
String id = makeId(atts);
NMethod nm = nmethods.get(id);
! if (nm == null) throw new InternalError();
LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
atts.getValue("zombie") != null, nm);
events.add(e);
} else if (qname.equals("uncommon_trap")) {
String id = atts.getValue("compile_id");
--- 1002,1012 ----
failureReason = null;
}
} else if (qname.equals("make_not_entrant")) {
String id = makeId(atts);
NMethod nm = nmethods.get(id);
! if (nm == null) reportInternalError("nm == null");
LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
atts.getValue("zombie") != null, nm);
events.add(e);
} else if (qname.equals("uncommon_trap")) {
String id = atts.getValue("compile_id");
*** 457,468 ****
atts.getValue("reason"),
atts.getValue("action"),
Integer.parseInt(search(atts, "count", "0")));
events.add(currentTrap);
} else {
! // uncommon trap inserted during parsing.
! // ignore for now
}
} else if (qname.startsWith("eliminate_lock")) {
String id = atts.getValue("compile_id");
if (id != null) {
id = makeId(atts);
--- 1017,1042 ----
atts.getValue("reason"),
atts.getValue("action"),
Integer.parseInt(search(atts, "count", "0")));
events.add(currentTrap);
} else {
! if (atts.getValue("method") != null) {
! // These are messages from ciTypeFlow that don't
! // actually correspond to generated code.
! return;
! }
! try {
! if (scopes.size() == 0) {
! reportInternalError("scope underflow");
! }
! scopes.peek().add(new UncommonTrap(Integer.parseInt(search(atts, "bci")),
! search(atts, "reason"),
! search(atts, "action"),
! bytecodes[current_bytecode]));
! } catch (Error e) {
! e.printStackTrace();
! }
}
} else if (qname.startsWith("eliminate_lock")) {
String id = atts.getValue("compile_id");
if (id != null) {
id = makeId(atts);
*** 472,507 ****
events.add(currentLockElimination);
}
} else if (qname.equals("late_inline")) {
long inlineId = 0;
try {
! Long.parseLong(search(atts, "inline_id"));
} catch (InternalError ex) {
// Log files from older hotspots may lack inline_id,
// and zero is an acceptable substitute that allows processing to continue.
}
! lateInlineScope = new Stack<CallSite>();
! site = new CallSite(-999, method(search(atts, "method")));
site.setInlineId(inlineId);
lateInlineScope.push(site);
} else if (qname.equals("jvms")) {
// <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
if (currentTrap != null) {
! currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
} else if (currentLockElimination != null) {
currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci")));
} else if (lateInlineScope != null) {
! bci = Integer.parseInt(search(atts, "bci"));
! site = new CallSite(bci, method(search(atts, "method")));
lateInlineScope.push(site);
} else {
// Ignore <eliminate_allocation type='667'>,
// <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
}
} else if (qname.equals("inline_id")) {
if (methodHandleSite != null) {
! throw new InternalError("method handle site should have been replaced");
}
long id = Long.parseLong(search(atts, "id"));
site.setInlineId(id);
} else if (qname.equals("nmethod")) {
String id = makeId(atts);
--- 1046,1084 ----
events.add(currentLockElimination);
}
} else if (qname.equals("late_inline")) {
long inlineId = 0;
try {
! inlineId = Long.parseLong(search(atts, "inline_id"));
} catch (InternalError ex) {
// Log files from older hotspots may lack inline_id,
// and zero is an acceptable substitute that allows processing to continue.
}
! lateInlineScope = new ArrayDeque<>();
! Method m = method(search(atts, "method"));
! site = new CallSite(-999, m);
site.setInlineId(inlineId);
lateInlineScope.push(site);
} else if (qname.equals("jvms")) {
// <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
if (currentTrap != null) {
! String[] parts = spacePattern.split(atts.getValue("method"));
! currentTrap.addMethodAndBCI(parts[0].replace('/', '.') + '.' + parts[1] + parts[2], Integer.parseInt(atts.getValue("bci")));
} else if (currentLockElimination != null) {
currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci")));
} else if (lateInlineScope != null) {
! current_bci = Integer.parseInt(search(atts, "bci"));
! Method m = method(search(atts, "method"));
! site = new CallSite(current_bci, m);
lateInlineScope.push(site);
} else {
// Ignore <eliminate_allocation type='667'>,
// <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
}
} else if (qname.equals("inline_id")) {
if (methodHandleSite != null) {
! reportInternalError("method handle site should have been replaced");
}
long id = Long.parseLong(search(atts, "id"));
site.setInlineId(id);
} else if (qname.equals("nmethod")) {
String id = makeId(atts);
*** 511,547 ****
parseLong(atts.getValue("size")));
nmethods.put(id, nm);
events.add(nm);
} else if (qname.equals("parse")) {
if (failureReason != null && scopes.size() == 0 && !lateInlining) {
failureReason = null;
compile.reset();
site = compile.getCall();
}
if (methodHandleSite != null) {
! throw new InternalError("method handle site should have been replaced");
}
! Method m = method(search(atts, "method"));
if (lateInlining && scopes.size() == 0) {
if (site.getMethod() != m) {
! System.out.println(site.getMethod());
! System.out.println(m);
! throw new InternalError("Unexpected method mismatch during late inlining");
}
}
if (scopes.size() == 0 && !lateInlining) {
compile.setMethod(m);
scopes.push(site);
} else {
if (site.getMethod() == m) {
scopes.push(site);
! } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().last(-2).getMethod()) {
! scopes.push(scopes.peek().last(-2));
} else {
! // C1 prints multiple method tags during inlining when it narrows method being inlinied.
! // Example:
// ...
// <method id="813" holder="694" name="toString" return="695" flags="1" bytes="36" iicount="1"/>
// <call method="813" instr="invokevirtual"/>
// <inline_success reason="receiver is statically known"/>
// <method id="814" holder="792" name="toString" return="695" flags="1" bytes="5" iicount="3"/>
--- 1088,1144 ----
parseLong(atts.getValue("size")));
nmethods.put(id, nm);
events.add(nm);
} else if (qname.equals("parse")) {
if (failureReason != null && scopes.size() == 0 && !lateInlining) {
+ // A compilation just failed, and we're back at a top
+ // compilation scope.
failureReason = null;
compile.reset();
site = compile.getCall();
}
+ // Error checking.
if (methodHandleSite != null) {
! reportInternalError("method handle site should have been replaced");
}
! Method m = method(search(atts, "method")); // this is the method being parsed
if (lateInlining && scopes.size() == 0) {
if (site.getMethod() != m) {
! reportInternalError("Unexpected method mismatch during late inlining (method at call site: " +
! site.getMethod() + ", method being parsed: " + m + ")");
}
}
+
if (scopes.size() == 0 && !lateInlining) {
+ // The method being parsed is actually the method being
+ // compiled; i.e., we're dealing with a compilation top scope,
+ // which we must consequently push to the scopes stack.
compile.setMethod(m);
scopes.push(site);
} else {
+ // The method being parsed is *not* the current compilation's
+ // top scope; i.e., we're dealing with an actual call site
+ // in the top scope or somewhere further down a call stack.
if (site.getMethod() == m) {
+ // We're dealing with monomorphic inlining that didn't have
+ // to be narrowed down, because the receiver was known
+ // beforehand.
scopes.push(site);
! } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().lastButOne().getMethod()) {
! // We're dealing with an at least bimorphic call site, and
! // the compiler has now decided to parse the last-but-one
! // method. The last one may already have been parsed for
! // inlining.
! scopes.push(scopes.peek().lastButOne());
} else {
! // The method has been narrowed down to the one we're now
! // going to parse, which is inlined here. It's monomorphic
! // inlining, but was not immediately clear as such.
! //
! // C1 prints multiple method tags during inlining when it
! // narrows the method being inlined. Example:
// ...
// <method id="813" holder="694" name="toString" return="695" flags="1" bytes="36" iicount="1"/>
// <call method="813" instr="invokevirtual"/>
// <inline_success reason="receiver is statically known"/>
// <method id="814" holder="792" name="toString" return="695" flags="1" bytes="5" iicount="3"/>
*** 550,573 ****
site.setMethod(m);
scopes.push(site);
}
}
} else if (qname.equals("parse_done")) {
! CallSite call = scopes.pop();
call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
- scopes.push(call);
}
}
@Override
! public void endElement(String uri,
! String localName,
! String qname) {
if (qname.equals("parse")) {
! indent -= 2;
scopes.pop();
if (scopes.size() == 0) {
lateInlining = false;
}
} else if (qname.equals("uncommon_trap")) {
--- 1147,1195 ----
site.setMethod(m);
scopes.push(site);
}
}
} else if (qname.equals("parse_done")) {
! // Attach collected information about IR nodes to the current
! // parsing scope before it's popped off the stack in endElement()
! // (see where the parse tag is handled).
! CallSite call = scopes.peek();
call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
}
}
+ /**
+ * Process the end of a compilation log XML element.<ul>
+ * <li><b>parse:</b> finish transforming a Java method's bytecode
+ * instructions to an initial compiler IR graph.</li>
+ * <li><b>uncommon_trap:</b> record the end of processing an uncommon trap,
+ * resetting {@link #currentTrap}.</li>
+ * <li><b>eliminate_lock:</b> record the end of a lock elimination,
+ * resetting {@link #currentLockElimination}.</li>
+ * <li><b>late_inline:</b> the closing tag for late_inline does not denote
+ * the end of a late inlining operation, but the end of the descriptive log
+ * data given at its beginning. That is, we're now in the position to
+ * assemble details about the inlining chain (bytecode instruction index in
+ * caller, called method). The {@link #lateInlining} flag is set to
+ * {@code true} here. (It will be reset when parsing the inlined methods is
+ * done; this happens for the successful case in this method as well, when
+ * {@code parse} elements are processed; and for inlining failures, in
+ * {@link #startElement()}, when {@code inline_fail} elements are
+ * processed.)</li>
+ * <li><b>task:</b> perform cleanup at the end of a compilation. Note that
+ * the explicit {@code task_done} event is handled in
+ * {@link #startElement()}.</li>
+ * </ul>
+ */
@Override
! public void endElement(String uri, String localName, String qname) {
! try {
if (qname.equals("parse")) {
! // Finish dealing with the current call scope. If no more are
! // left, no late inlining can be going on.
scopes.pop();
if (scopes.size() == 0) {
lateInlining = false;
}
} else if (qname.equals("uncommon_trap")) {
*** 575,652 ****
} else if (qname.startsWith("eliminate_lock")) {
currentLockElimination = null;
} else if (qname.equals("late_inline")) {
// Populate late inlining info.
if (scopes.size() != 0) {
! throw new InternalError("scopes should be empty for late inline");
}
// late inline scopes are specified in reverse order:
// compiled method should be on top of stack.
CallSite caller = lateInlineScope.pop();
Method m = compile.getMethod();
! if (m != caller.getMethod()) {
! System.err.println(m);
! System.err.println(caller.getMethod() + " bci: " + bci);
! throw new InternalError("call site and late_inline info don't match");
}
! // late_inline contains caller+bci info, convert it
! // to bci+callee info used by LogCompilation.
CallSite lateInlineSite = compile.getLateInlineCall();
! ArrayDeque<CallSite> thisCallScopes = new ArrayDeque<CallSite>();
do {
! bci = caller.getBci();
// Next inlined call.
caller = lateInlineScope.pop();
! CallSite callee = new CallSite(bci, caller.getMethod());
callee.setInlineId(caller.getInlineId());
thisCallScopes.addLast(callee);
lateInlineSite.add(callee);
lateInlineSite = callee;
! } while (!lateInlineScope.empty());
site = compile.getCall().findCallSite(thisCallScopes);
if (site == null) {
! System.out.println("call scopes:");
for (CallSite c : thisCallScopes) {
! System.out.println(c.getMethod() + " " + c.getBci() + " " + c.getInlineId());
}
CallSite c = thisCallScopes.getLast();
if (c.getInlineId() != 0) {
! System.out.println("Looking for call site in entire tree:");
ArrayDeque<CallSite> stack = compile.getCall().findCallSite2(c);
for (CallSite c2 : stack) {
! System.out.println(c2.getMethod() + " " + c2.getBci() + " " + c2.getInlineId());
}
}
! System.out.println(caller.getMethod() + " bci: " + bci);
! throw new InternalError("couldn't find call site");
}
lateInlining = true;
if (caller.getBci() != -999) {
System.out.println(caller.getMethod());
! throw new InternalError("broken late_inline info");
}
if (site.getMethod() != caller.getMethod()) {
if (site.getInlineId() == caller.getInlineId()) {
site.setMethod(caller.getMethod());
} else {
System.out.println(site.getMethod());
System.out.println(caller.getMethod());
! throw new InternalError("call site and late_inline info don't match");
}
}
// late_inline is followed by parse with scopes.size() == 0,
// 'site' will be pushed to scopes.
lateInlineScope = null;
} else if (qname.equals("task")) {
types.clear();
methods.clear();
site = null;
}
}
@Override
public void warning(org.xml.sax.SAXParseException e) {
System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
e.printStackTrace();
--- 1197,1281 ----
} else if (qname.startsWith("eliminate_lock")) {
currentLockElimination = null;
} else if (qname.equals("late_inline")) {
// Populate late inlining info.
if (scopes.size() != 0) {
! reportInternalError("scopes should be empty for late inline");
}
// late inline scopes are specified in reverse order:
// compiled method should be on top of stack.
CallSite caller = lateInlineScope.pop();
Method m = compile.getMethod();
! if (!m.equals(caller.getMethod())) {
! reportInternalError(String.format("call site and late_inline info don't match:\n method %s\n caller method %s, bci %d", m, caller.getMethod(), current_bci));
}
! // Walk down the inlining chain and assemble bci+callee info.
! // This needs to be converted from caller+bci info contained in
! // the late_inline data.
CallSite lateInlineSite = compile.getLateInlineCall();
! ArrayDeque<CallSite> thisCallScopes = new ArrayDeque<>();
do {
! current_bci = caller.getBci();
// Next inlined call.
caller = lateInlineScope.pop();
! CallSite callee = new CallSite(current_bci, caller.getMethod());
callee.setInlineId(caller.getInlineId());
thisCallScopes.addLast(callee);
lateInlineSite.add(callee);
lateInlineSite = callee;
! } while (!lateInlineScope.isEmpty());
site = compile.getCall().findCallSite(thisCallScopes);
if (site == null) {
! // Call site could not be found - report the problem in detail.
! System.err.println("call scopes:");
for (CallSite c : thisCallScopes) {
! System.err.println(c.getMethod() + " " + c.getBci() + " " + c.getInlineId());
}
CallSite c = thisCallScopes.getLast();
if (c.getInlineId() != 0) {
! System.err.println("Looking for call site in entire tree:");
ArrayDeque<CallSite> stack = compile.getCall().findCallSite2(c);
for (CallSite c2 : stack) {
! System.err.println(c2.getMethod() + " " + c2.getBci() + " " + c2.getInlineId());
}
}
! System.err.println(caller.getMethod() + " bci: " + current_bci);
! reportInternalError("couldn't find call site");
}
lateInlining = true;
if (caller.getBci() != -999) {
System.out.println(caller.getMethod());
! reportInternalError("broken late_inline info");
}
if (site.getMethod() != caller.getMethod()) {
if (site.getInlineId() == caller.getInlineId()) {
site.setMethod(caller.getMethod());
} else {
System.out.println(site.getMethod());
System.out.println(caller.getMethod());
! reportInternalError("call site and late_inline info don't match");
}
}
// late_inline is followed by parse with scopes.size() == 0,
// 'site' will be pushed to scopes.
lateInlineScope = null;
} else if (qname.equals("task")) {
types.clear();
methods.clear();
site = null;
}
+ } catch (Exception e) {
+ reportInternalError("exception while processing end element", e);
}
+ }
+
+ //
+ // Handlers for problems that occur in XML parsing itself.
+ //
@Override
public void warning(org.xml.sax.SAXParseException e) {
System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
e.printStackTrace();
< prev index next >