< 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 >