1 /* 2 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 /** 26 * A SAX based parser of LogCompilation output from HotSpot. It takes a complete 27 * @author never 28 */ 29 30 package com.sun.hotspot.tools.compiler; 31 32 import java.io.FileReader; 33 import java.io.Reader; 34 import java.util.ArrayDeque; 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.Comparator; 38 import java.util.HashMap; 39 import java.util.LinkedHashMap; 40 import java.util.Stack; 41 import javax.xml.parsers.SAXParser; 42 import javax.xml.parsers.SAXParserFactory; 43 import org.xml.sax.Attributes; 44 import org.xml.sax.ErrorHandler; 45 import org.xml.sax.InputSource; 46 import org.xml.sax.helpers.DefaultHandler; 47 48 public class LogParser extends DefaultHandler implements ErrorHandler, Constants { 49 50 static final HashMap<String, String> typeMap; 51 static { 52 typeMap = new HashMap<String, String>(); 117 if (difference < 0) { 118 return -1; 119 } 120 if (difference > 0) { 121 return 1; 122 } 123 return 0; 124 } 125 126 @Override 127 public boolean equals(Object other) { 128 return false; 129 } 130 131 @Override 132 public int hashCode() { 133 return 7; 134 } 135 }; 136 137 private ArrayList<LogEvent> events = new ArrayList<LogEvent>(); 138 139 private HashMap<String, String> types = new HashMap<String, String>(); 140 private HashMap<String, Method> methods = new HashMap<String, Method>(); 141 private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<String, NMethod>(); 142 private HashMap<String, Compilation> compiles = new HashMap<String, Compilation>(); 143 private String failureReason; 144 private int bci; 145 private Stack<CallSite> scopes = new Stack<CallSite>(); 146 private Compilation compile; 147 private CallSite site; 148 private CallSite methodHandleSite; 149 private Stack<Phase> phaseStack = new Stack<Phase>(); 150 private UncommonTrapEvent currentTrap; 151 private Stack<CallSite> lateInlineScope; 152 private boolean lateInlining; 153 154 155 long parseLong(String l) { 156 try { 175 } 176 177 public static ArrayList<LogEvent> parse(String file, boolean cleanup) throws Exception { 178 return parse(new FileReader(file), cleanup); 179 } 180 181 public static ArrayList<LogEvent> parse(Reader reader, boolean cleanup) throws Exception { 182 // Create the XML input factory 183 SAXParserFactory factory = SAXParserFactory.newInstance(); 184 185 // Create the XML LogEvent reader 186 SAXParser p = factory.newSAXParser(); 187 188 if (cleanup) { 189 // some versions of the log have slightly malformed XML, so clean it 190 // up before passing it to SAX 191 reader = new LogCleanupReader(reader); 192 } 193 194 LogParser log = new LogParser(); 195 p.parse(new InputSource(reader), log); 196 197 // Associate compilations with their NMethods 198 for (NMethod nm : log.nmethods.values()) { 199 Compilation c = log.compiles.get(nm.getId()); 200 nm.setCompilation(c); 201 // Native wrappers for methods don't have a compilation 202 if (c != null) { 203 c.setNMethod(nm); 204 } 205 } 206 207 // Initially we want the LogEvent log sorted by timestamp 208 Collections.sort(log.events, sortByStart); 209 210 return log.events; 211 } 212 213 String search(Attributes attr, String name) { 214 String result = attr.getValue(name); 215 if (result != null) { 401 String id = makeId(atts); 402 NMethod nm = nmethods.get(id); 403 if (nm == null) throw new InternalError(); 404 LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id, 405 atts.getValue("zombie") != null, nm); 406 events.add(e); 407 } else if (qname.equals("uncommon_trap")) { 408 String id = atts.getValue("compile_id"); 409 if (id != null) { 410 id = makeId(atts); 411 currentTrap = new UncommonTrapEvent(Double.parseDouble(search(atts, "stamp")), 412 id, 413 atts.getValue("reason"), 414 atts.getValue("action"), 415 Integer.parseInt(search(atts, "count", "0"))); 416 events.add(currentTrap); 417 } else { 418 // uncommon trap inserted during parsing. 419 // ignore for now 420 } 421 } else if (qname.equals("late_inline")) { 422 long inlineId = Long.parseLong(search(atts, "inline_id")); 423 lateInlineScope = new Stack<CallSite>(); 424 site = new CallSite(-999, method(search(atts, "method"))); 425 site.setInlineId(inlineId); 426 lateInlineScope.push(site); 427 } else if (qname.equals("jvms")) { 428 // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/> 429 if (currentTrap != null) { 430 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); 431 } else if (lateInlineScope != null) { 432 bci = Integer.parseInt(search(atts, "bci")); 433 site = new CallSite(bci, method(search(atts, "method"))); 434 lateInlineScope.push(site); 435 } else { 436 // Ignore <eliminate_allocation type='667'>, 437 // <eliminate_lock lock='1'>, 438 // <replace_string_concat arguments='2' string_alloc='0' multiple='0'> 439 } 440 } else if (qname.equals("inline_id")) { 495 CallSite call = scopes.pop(); 496 call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0"))); 497 call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0"))); 498 call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); 499 scopes.push(call); 500 } 501 } 502 503 @Override 504 public void endElement(String uri, 505 String localName, 506 String qname) { 507 if (qname.equals("parse")) { 508 indent -= 2; 509 scopes.pop(); 510 if (scopes.size() == 0) { 511 lateInlining = false; 512 } 513 } else if (qname.equals("uncommon_trap")) { 514 currentTrap = null; 515 } else if (qname.equals("late_inline")) { 516 // Populate late inlining info. 517 if (scopes.size() != 0) { 518 throw new InternalError("scopes should be empty for late inline"); 519 } 520 // late inline scopes are specified in reverse order: 521 // compiled method should be on top of stack. 522 CallSite caller = lateInlineScope.pop(); 523 Method m = compile.getMethod(); 524 if (m != caller.getMethod()) { 525 System.out.println(m); 526 System.out.println(caller.getMethod() + " bci: " + bci); 527 throw new InternalError("call site and late_inline info don't match"); 528 } 529 530 // late_inline contains caller+bci info, convert it 531 // to bci+callee info used by LogCompilation. 532 CallSite lateInlineSite = compile.getLateInlineCall(); 533 ArrayDeque<CallSite> thisCallScopes = new ArrayDeque<CallSite>(); 534 do { 535 bci = caller.getBci(); 536 // Next inlined call. 537 caller = lateInlineScope.pop(); 538 CallSite callee = new CallSite(bci, caller.getMethod()); 539 callee.setInlineId(caller.getInlineId()); 540 thisCallScopes.addLast(callee); 541 lateInlineSite.add(callee); 542 lateInlineSite = callee; 543 } while (!lateInlineScope.empty()); 544 545 site = compile.getCall().findCallSite(thisCallScopes); 546 if (site == null) { | 1 /* 2 * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 /** 26 * A SAX based parser of LogCompilation output from HotSpot. It takes a complete 27 */ 28 29 package com.sun.hotspot.tools.compiler; 30 31 import java.io.FileReader; 32 import java.io.PrintStream; 33 import java.io.Reader; 34 import java.util.ArrayDeque; 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.Comparator; 38 import java.util.HashMap; 39 import java.util.LinkedHashMap; 40 import java.util.Stack; 41 import javax.xml.parsers.SAXParser; 42 import javax.xml.parsers.SAXParserFactory; 43 import org.xml.sax.Attributes; 44 import org.xml.sax.ErrorHandler; 45 import org.xml.sax.InputSource; 46 import org.xml.sax.helpers.DefaultHandler; 47 48 public class LogParser extends DefaultHandler implements ErrorHandler, Constants { 49 50 static final HashMap<String, String> typeMap; 51 static { 52 typeMap = new HashMap<String, String>(); 117 if (difference < 0) { 118 return -1; 119 } 120 if (difference > 0) { 121 return 1; 122 } 123 return 0; 124 } 125 126 @Override 127 public boolean equals(Object other) { 128 return false; 129 } 130 131 @Override 132 public int hashCode() { 133 return 7; 134 } 135 }; 136 137 class Jvms { 138 Jvms(Method method, int bci) { 139 this.method = method; 140 this.bci = bci; 141 } 142 final public Method method; 143 final public int bci; 144 final public String toString() { 145 return "@" + bci + " " + method; 146 } 147 } 148 149 class LockElimination extends BasicLogEvent { 150 151 ArrayList<Jvms> jvms = new ArrayList<Jvms>(1); 152 final String kind; 153 final String classId; 154 final String tagName; 155 LockElimination(String tagName, double start, String id, String kind, String classId) { 156 super(start, id); 157 this.kind = kind; 158 this.classId = classId; 159 this.tagName = tagName; 160 } 161 162 @Override 163 public void print(PrintStream stream) { 164 stream.printf("%s %s %s %s %.3f ", getId(), tagName, kind, classId, getStart()); 165 stream.print(jvms.toString()); 166 stream.print("\n"); 167 } 168 169 void addJVMS(Method method, int bci) { 170 jvms.add(new Jvms(method, bci)); 171 } 172 173 } 174 175 private ArrayList<LogEvent> events = new ArrayList<LogEvent>(); 176 177 private HashMap<String, String> types = new HashMap<String, String>(); 178 private HashMap<String, Method> methods = new HashMap<String, Method>(); 179 private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<String, NMethod>(); 180 private HashMap<String, Compilation> compiles = new HashMap<String, Compilation>(); 181 private String failureReason; 182 private int bci; 183 private Stack<CallSite> scopes = new Stack<CallSite>(); 184 private Compilation compile; 185 private CallSite site; 186 private CallSite methodHandleSite; 187 private Stack<Phase> phaseStack = new Stack<Phase>(); 188 private UncommonTrapEvent currentTrap; 189 private Stack<CallSite> lateInlineScope; 190 private boolean lateInlining; 191 192 193 long parseLong(String l) { 194 try { 213 } 214 215 public static ArrayList<LogEvent> parse(String file, boolean cleanup) throws Exception { 216 return parse(new FileReader(file), cleanup); 217 } 218 219 public static ArrayList<LogEvent> parse(Reader reader, boolean cleanup) throws Exception { 220 // Create the XML input factory 221 SAXParserFactory factory = SAXParserFactory.newInstance(); 222 223 // Create the XML LogEvent reader 224 SAXParser p = factory.newSAXParser(); 225 226 if (cleanup) { 227 // some versions of the log have slightly malformed XML, so clean it 228 // up before passing it to SAX 229 reader = new LogCleanupReader(reader); 230 } 231 232 LogParser log = new LogParser(); 233 try { 234 p.parse(new InputSource(reader), log); 235 } catch (Throwable th) { 236 th.printStackTrace(); 237 // Carry on with what we've got... 238 } 239 240 // Associate compilations with their NMethods 241 for (NMethod nm : log.nmethods.values()) { 242 Compilation c = log.compiles.get(nm.getId()); 243 nm.setCompilation(c); 244 // Native wrappers for methods don't have a compilation 245 if (c != null) { 246 c.setNMethod(nm); 247 } 248 } 249 250 // Initially we want the LogEvent log sorted by timestamp 251 Collections.sort(log.events, sortByStart); 252 253 return log.events; 254 } 255 256 String search(Attributes attr, String name) { 257 String result = attr.getValue(name); 258 if (result != null) { 444 String id = makeId(atts); 445 NMethod nm = nmethods.get(id); 446 if (nm == null) throw new InternalError(); 447 LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id, 448 atts.getValue("zombie") != null, nm); 449 events.add(e); 450 } else if (qname.equals("uncommon_trap")) { 451 String id = atts.getValue("compile_id"); 452 if (id != null) { 453 id = makeId(atts); 454 currentTrap = new UncommonTrapEvent(Double.parseDouble(search(atts, "stamp")), 455 id, 456 atts.getValue("reason"), 457 atts.getValue("action"), 458 Integer.parseInt(search(atts, "count", "0"))); 459 events.add(currentTrap); 460 } else { 461 // uncommon trap inserted during parsing. 462 // ignore for now 463 } 464 } else if (qname.startsWith("eliminate_lock")) { 465 String id = atts.getValue("compile_id"); 466 if (id != null) { 467 id = makeId(atts); 468 String kind = atts.getValue("kind"); 469 String classId = atts.getValue("class_id"); 470 currentLockElimination = new LockElimination(qname, Double.parseDouble(search(atts, "stamp")), id, kind, classId); 471 events.add(currentLockElimination); 472 } 473 } else if (qname.equals("late_inline")) { 474 long inlineId = Long.parseLong(search(atts, "inline_id")); 475 lateInlineScope = new Stack<CallSite>(); 476 site = new CallSite(-999, method(search(atts, "method"))); 477 site.setInlineId(inlineId); 478 lateInlineScope.push(site); 479 } else if (qname.equals("jvms")) { 480 // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/> 481 if (currentTrap != null) { 482 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); 483 } else if (lateInlineScope != null) { 484 bci = Integer.parseInt(search(atts, "bci")); 485 site = new CallSite(bci, method(search(atts, "method"))); 486 lateInlineScope.push(site); 487 } else { 488 // Ignore <eliminate_allocation type='667'>, 489 // <eliminate_lock lock='1'>, 490 // <replace_string_concat arguments='2' string_alloc='0' multiple='0'> 491 } 492 } else if (qname.equals("inline_id")) { 547 CallSite call = scopes.pop(); 548 call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0"))); 549 call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0"))); 550 call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); 551 scopes.push(call); 552 } 553 } 554 555 @Override 556 public void endElement(String uri, 557 String localName, 558 String qname) { 559 if (qname.equals("parse")) { 560 indent -= 2; 561 scopes.pop(); 562 if (scopes.size() == 0) { 563 lateInlining = false; 564 } 565 } else if (qname.equals("uncommon_trap")) { 566 currentTrap = null; 567 } else if (qname.startsWith("eliminate_lock")) { 568 currentLockElimination = null; 569 } else if (qname.equals("late_inline")) { 570 // Populate late inlining info. 571 if (scopes.size() != 0) { 572 throw new InternalError("scopes should be empty for late inline"); 573 } 574 // late inline scopes are specified in reverse order: 575 // compiled method should be on top of stack. 576 CallSite caller = lateInlineScope.pop(); 577 Method m = compile.getMethod(); 578 if (m != caller.getMethod()) { 579 System.err.println(m); 580 System.err.println(caller.getMethod() + " bci: " + bci); 581 throw new InternalError("call site and late_inline info don't match"); 582 } 583 584 // late_inline contains caller+bci info, convert it 585 // to bci+callee info used by LogCompilation. 586 CallSite lateInlineSite = compile.getLateInlineCall(); 587 ArrayDeque<CallSite> thisCallScopes = new ArrayDeque<CallSite>(); 588 do { 589 bci = caller.getBci(); 590 // Next inlined call. 591 caller = lateInlineScope.pop(); 592 CallSite callee = new CallSite(bci, caller.getMethod()); 593 callee.setInlineId(caller.getInlineId()); 594 thisCallScopes.addLast(callee); 595 lateInlineSite.add(callee); 596 lateInlineSite = callee; 597 } while (!lateInlineScope.empty()); 598 599 site = compile.getCall().findCallSite(thisCallScopes); 600 if (site == null) { |