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 {
157 return Long.decode(l).longValue();
158 } catch (NumberFormatException nfe) {
159 int split = l.length() - 8;
160 String s1 = "0x" + l.substring(split);
161 String s2 = l.substring(0, split);
162 long v1 = Long.decode(s1).longValue() & 0xffffffffL;
163 long v2 = (Long.decode(s2).longValue() & 0xffffffffL) << 32;
164 if (!l.equals("0x" + Long.toHexString(v1 + v2))) {
165 System.out.println(l);
166 System.out.println(s1);
167 System.out.println(s2);
168 System.out.println(v1);
169 System.out.println(v2);
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")) {
441 if (methodHandleSite != null) {
442 throw new InternalError("method handle site should have been replaced");
443 }
444 long id = Long.parseLong(search(atts, "id"));
445 site.setInlineId(id);
446 } else if (qname.equals("nmethod")) {
447 String id = makeId(atts);
448 NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")),
449 id,
450 parseLong(atts.getValue("address")),
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 LockElimination currentLockElimination;
189 private UncommonTrapEvent currentTrap;
190 private Stack<CallSite> lateInlineScope;
191 private boolean lateInlining;
192
193
194 long parseLong(String l) {
195 try {
196 return Long.decode(l).longValue();
197 } catch (NumberFormatException nfe) {
198 int split = l.length() - 8;
199 String s1 = "0x" + l.substring(split);
200 String s2 = l.substring(0, split);
201 long v1 = Long.decode(s1).longValue() & 0xffffffffL;
202 long v2 = (Long.decode(s2).longValue() & 0xffffffffL) << 32;
203 if (!l.equals("0x" + Long.toHexString(v1 + v2))) {
204 System.out.println(l);
205 System.out.println(s1);
206 System.out.println(s2);
207 System.out.println(v1);
208 System.out.println(v2);
214 }
215
216 public static ArrayList<LogEvent> parse(String file, boolean cleanup) throws Exception {
217 return parse(new FileReader(file), cleanup);
218 }
219
220 public static ArrayList<LogEvent> parse(Reader reader, boolean cleanup) throws Exception {
221 // Create the XML input factory
222 SAXParserFactory factory = SAXParserFactory.newInstance();
223
224 // Create the XML LogEvent reader
225 SAXParser p = factory.newSAXParser();
226
227 if (cleanup) {
228 // some versions of the log have slightly malformed XML, so clean it
229 // up before passing it to SAX
230 reader = new LogCleanupReader(reader);
231 }
232
233 LogParser log = new LogParser();
234 try {
235 p.parse(new InputSource(reader), log);
236 } catch (Throwable th) {
237 th.printStackTrace();
238 // Carry on with what we've got...
239 }
240
241 // Associate compilations with their NMethods
242 for (NMethod nm : log.nmethods.values()) {
243 Compilation c = log.compiles.get(nm.getId());
244 nm.setCompilation(c);
245 // Native wrappers for methods don't have a compilation
246 if (c != null) {
247 c.setNMethod(nm);
248 }
249 }
250
251 // Initially we want the LogEvent log sorted by timestamp
252 Collections.sort(log.events, sortByStart);
253
254 return log.events;
255 }
256
257 String search(Attributes attr, String name) {
258 String result = attr.getValue(name);
259 if (result != null) {
445 String id = makeId(atts);
446 NMethod nm = nmethods.get(id);
447 if (nm == null) throw new InternalError();
448 LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
449 atts.getValue("zombie") != null, nm);
450 events.add(e);
451 } else if (qname.equals("uncommon_trap")) {
452 String id = atts.getValue("compile_id");
453 if (id != null) {
454 id = makeId(atts);
455 currentTrap = new UncommonTrapEvent(Double.parseDouble(search(atts, "stamp")),
456 id,
457 atts.getValue("reason"),
458 atts.getValue("action"),
459 Integer.parseInt(search(atts, "count", "0")));
460 events.add(currentTrap);
461 } else {
462 // uncommon trap inserted during parsing.
463 // ignore for now
464 }
465 } else if (qname.startsWith("eliminate_lock")) {
466 String id = atts.getValue("compile_id");
467 if (id != null) {
468 id = makeId(atts);
469 String kind = atts.getValue("kind");
470 String classId = atts.getValue("class_id");
471 currentLockElimination = new LockElimination(qname, Double.parseDouble(search(atts, "stamp")), id, kind, classId);
472 events.add(currentLockElimination);
473 }
474 } else if (qname.equals("late_inline")) {
475 long inlineId = 0;
476 try {
477 Long.parseLong(search(atts, "inline_id"));
478 } catch (InternalError ex) {
479 // 0 is an acceptable default value.
480 }
481 lateInlineScope = new Stack<CallSite>();
482 site = new CallSite(-999, method(search(atts, "method")));
483 site.setInlineId(inlineId);
484 lateInlineScope.push(site);
485 } else if (qname.equals("jvms")) {
486 // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
487 if (currentTrap != null) {
488 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
489 } else if (currentLockElimination != null) {
490 currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci")));
491 } else if (lateInlineScope != null) {
492 bci = Integer.parseInt(search(atts, "bci"));
493 site = new CallSite(bci, method(search(atts, "method")));
494 lateInlineScope.push(site);
495 } else {
496 // Ignore <eliminate_allocation type='667'>,
497 // <eliminate_lock lock='1'>,
498 // <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
499 }
500 } else if (qname.equals("inline_id")) {
501 if (methodHandleSite != null) {
502 throw new InternalError("method handle site should have been replaced");
503 }
504 long id = Long.parseLong(search(atts, "id"));
505 site.setInlineId(id);
506 } else if (qname.equals("nmethod")) {
507 String id = makeId(atts);
508 NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")),
509 id,
510 parseLong(atts.getValue("address")),
555 CallSite call = scopes.pop();
556 call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
557 call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
558 call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
559 scopes.push(call);
560 }
561 }
562
563 @Override
564 public void endElement(String uri,
565 String localName,
566 String qname) {
567 if (qname.equals("parse")) {
568 indent -= 2;
569 scopes.pop();
570 if (scopes.size() == 0) {
571 lateInlining = false;
572 }
573 } else if (qname.equals("uncommon_trap")) {
574 currentTrap = null;
575 } else if (qname.startsWith("eliminate_lock")) {
576 currentLockElimination = null;
577 } else if (qname.equals("late_inline")) {
578 // Populate late inlining info.
579 if (scopes.size() != 0) {
580 throw new InternalError("scopes should be empty for late inline");
581 }
582 // late inline scopes are specified in reverse order:
583 // compiled method should be on top of stack.
584 CallSite caller = lateInlineScope.pop();
585 Method m = compile.getMethod();
586 if (m != caller.getMethod()) {
587 System.err.println(m);
588 System.err.println(caller.getMethod() + " bci: " + bci);
589 throw new InternalError("call site and late_inline info don't match");
590 }
591
592 // late_inline contains caller+bci info, convert it
593 // to bci+callee info used by LogCompilation.
594 CallSite lateInlineSite = compile.getLateInlineCall();
595 ArrayDeque<CallSite> thisCallScopes = new ArrayDeque<CallSite>();
596 do {
597 bci = caller.getBci();
598 // Next inlined call.
599 caller = lateInlineScope.pop();
600 CallSite callee = new CallSite(bci, caller.getMethod());
601 callee.setInlineId(caller.getInlineId());
602 thisCallScopes.addLast(callee);
603 lateInlineSite.add(callee);
604 lateInlineSite = callee;
605 } while (!lateInlineScope.empty());
606
607 site = compile.getCall().findCallSite(thisCallScopes);
608 if (site == null) {
|