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.ArrayList;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.HashMap;
38 import java.util.LinkedHashMap;
39 import java.util.Stack;
40 import javax.xml.parsers.SAXParser;
41 import javax.xml.parsers.SAXParserFactory;
42 import org.xml.sax.Attributes;
43 import org.xml.sax.ErrorHandler;
44 import org.xml.sax.InputSource;
45 import org.xml.sax.helpers.DefaultHandler;
46
47 public class LogParser extends DefaultHandler implements ErrorHandler, Constants {
48
49 static final HashMap<String, String> typeMap;
50 static {
51 typeMap = new HashMap<String, String>();
52 typeMap.put("[I", "int[]");
53 typeMap.put("[C", "char[]");
127 return false;
128 }
129
130 @Override
131 public int hashCode() {
132 return 7;
133 }
134 };
135
136 private ArrayList<LogEvent> events = new ArrayList<LogEvent>();
137
138 private HashMap<String, String> types = new HashMap<String, String>();
139 private HashMap<String, Method> methods = new HashMap<String, Method>();
140 private LinkedHashMap<String, NMethod> nmethods = new LinkedHashMap<String, NMethod>();
141 private HashMap<String, Compilation> compiles = new HashMap<String, Compilation>();
142 private String failureReason;
143 private int bci;
144 private Stack<CallSite> scopes = new Stack<CallSite>();
145 private Compilation compile;
146 private CallSite site;
147 private Stack<Phase> phaseStack = new Stack<Phase>();
148 private UncommonTrapEvent currentTrap;
149 private Stack<CallSite> late_inline_scope;
150
151 long parseLong(String l) {
152 try {
153 return Long.decode(l).longValue();
154 } catch (NumberFormatException nfe) {
155 int split = l.length() - 8;
156 String s1 = "0x" + l.substring(split);
157 String s2 = l.substring(0, split);
158 long v1 = Long.decode(s1).longValue() & 0xffffffffL;
159 long v2 = (Long.decode(s2).longValue() & 0xffffffffL) << 32;
160 if (!l.equals("0x" + Long.toHexString(v1 + v2))) {
161 System.out.println(l);
162 System.out.println(s1);
163 System.out.println(s2);
164 System.out.println(v1);
165 System.out.println(v2);
166 System.out.println(Long.toHexString(v1 + v2));
167 throw new InternalError("bad conversion");
168 }
169 return v1 + v2;
313 type(search(atts, "id"), search(atts, "name"));
314 } else if (qname.equals("bc")) {
315 bci = Integer.parseInt(search(atts, "bci"));
316 } else if (qname.equals("klass")) {
317 type(search(atts, "id"), search(atts, "name"));
318 } else if (qname.equals("method")) {
319 String id = search(atts, "id");
320 Method m = new Method();
321 m.setHolder(type(search(atts, "holder")));
322 m.setName(search(atts, "name"));
323 m.setReturnType(type(search(atts, "return")));
324 m.setArguments(search(atts, "arguments", "void"));
325
326 if (search(atts, "unloaded", "0").equals("0")) {
327 m.setBytes(search(atts, "bytes"));
328 m.setIICount(search(atts, "iicount"));
329 m.setFlags(search(atts, "flags"));
330 }
331 methods.put(id, m);
332 } else if (qname.equals("call")) {
333 site = new CallSite(bci, method(search(atts, "method")));
334 site.setCount(Integer.parseInt(search(atts, "count", "0")));
335 String receiver = atts.getValue("receiver");
336 if (receiver != null) {
337 site.setReceiver(type(receiver));
338 site.setReceiver_count(Integer.parseInt(search(atts, "receiver_count")));
339 }
340 scopes.peek().add(site);
341 } else if (qname.equals("regalloc")) {
342 compile.setAttempts(Integer.parseInt(search(atts, "attempts")));
343 } else if (qname.equals("inline_fail")) {
344 scopes.peek().last().setReason(search(atts, "reason"));
345 } else if (qname.equals("failure")) {
346 failureReason = search(atts, "reason");
347 } else if (qname.equals("task_done")) {
348 compile.setEnd(Double.parseDouble(search(atts, "stamp")));
349 if (Integer.parseInt(search(atts, "success")) == 0) {
350 compile.setFailureReason(failureReason);
351 }
352 } else if (qname.equals("make_not_entrant")) {
353 String id = makeId(atts);
354 NMethod nm = nmethods.get(id);
355 if (nm == null) throw new InternalError();
356 LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
357 atts.getValue("zombie") != null, nm);
358 events.add(e);
359 } else if (qname.equals("uncommon_trap")) {
360 String id = atts.getValue("compile_id");
361 if (id != null) {
362 id = makeId(atts);
363 currentTrap = new UncommonTrapEvent(Double.parseDouble(search(atts, "stamp")),
364 id,
365 atts.getValue("reason"),
366 atts.getValue("action"),
367 Integer.parseInt(search(atts, "count", "0")));
368 events.add(currentTrap);
369 } else {
370 // uncommon trap inserted during parsing.
371 // ignore for now
372 }
373 } else if (qname.equals("late_inline")) {
374 late_inline_scope = new Stack<CallSite>();
375 site = new CallSite(-999, method(search(atts, "method")));
376 late_inline_scope.push(site);
377 } else if (qname.equals("jvms")) {
378 // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
379 if (currentTrap != null) {
380 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
381 } else if (late_inline_scope != null) {
382 bci = Integer.parseInt(search(atts, "bci"));
383 site = new CallSite(bci, method(search(atts, "method")));
384 late_inline_scope.push(site);
385 } else {
386 // Ignore <eliminate_allocation type='667'>,
387 // <eliminate_lock lock='1'>,
388 // <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
389 }
390 } else if (qname.equals("nmethod")) {
391 String id = makeId(atts);
392 NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")),
393 id,
394 parseLong(atts.getValue("address")),
395 parseLong(atts.getValue("size")));
396 nmethods.put(id, nm);
397 events.add(nm);
398 } else if (qname.equals("parse")) {
399 Method m = method(search(atts, "method"));
400 if (scopes.size() == 0) {
401 compile.setMethod(m);
402 scopes.push(site);
403 } else {
404 if (site.getMethod() == m) {
405 scopes.push(site);
406 } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().last(-2).getMethod()) {
407 scopes.push(scopes.peek().last(-2));
408 } else {
409 System.out.println(site.getMethod());
410 System.out.println(m);
411 throw new InternalError("call site and parse don't match");
412 }
413 }
414 } else if (qname.equals("parse_done")) {
415 CallSite call = scopes.pop();
416 call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
417 call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
418 call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
419 scopes.push(call);
420 }
421 }
422
423 @Override
424 public void endElement(String uri,
425 String localName,
426 String qname) {
427 if (qname.equals("parse")) {
428 indent -= 2;
429 scopes.pop();
430 } else if (qname.equals("uncommon_trap")) {
431 currentTrap = null;
432 } else if (qname.equals("late_inline")) {
433 // Populate late inlining info.
434
435 // late_inline scopes are specified in reverse order:
436 // compiled method should be on top of stack.
437 CallSite caller = late_inline_scope.pop();
438 Method m = compile.getMethod();
439 if (m != caller.getMethod()) {
440 System.out.println(m);
441 System.out.println(caller.getMethod() + " bci: " + bci);
442 throw new InternalError("call site and late_inline info don't match");
443 }
444
445 // late_inline contains caller+bci info, convert it
446 // to bci+callee info used by LogCompilation.
447 site = compile.getLateInlineCall();
448 do {
449 bci = caller.getBci();
450 // Next inlined call.
451 caller = late_inline_scope.pop();
452 CallSite callee = new CallSite(bci, caller.getMethod());
453 site.add(callee);
454 site = callee;
455 } while (!late_inline_scope.empty());
456
457 if (caller.getBci() != -999) {
458 System.out.println(caller.getMethod());
459 throw new InternalError("broken late_inline info");
460 }
461 if (site.getMethod() != caller.getMethod()) {
462 System.out.println(site.getMethod());
463 System.out.println(caller.getMethod());
464 throw new InternalError("call site and late_inline info don't match");
465 }
466 // late_inline is followed by parse with scopes.size() == 0,
467 // 'site' will be pushed to scopes.
468 late_inline_scope = null;
469 } else if (qname.equals("task")) {
470 types.clear();
471 methods.clear();
472 site = null;
473 }
474 }
475
476 @Override
477 public void warning(org.xml.sax.SAXParseException e) {
478 System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
479 e.printStackTrace();
480 }
481
482 @Override
483 public void error(org.xml.sax.SAXParseException e) {
484 System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
485 e.printStackTrace();
486 }
487
488 @Override
|
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>();
53 typeMap.put("[I", "int[]");
54 typeMap.put("[C", "char[]");
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);
170 System.out.println(Long.toHexString(v1 + v2));
171 throw new InternalError("bad conversion");
172 }
173 return v1 + v2;
317 type(search(atts, "id"), search(atts, "name"));
318 } else if (qname.equals("bc")) {
319 bci = Integer.parseInt(search(atts, "bci"));
320 } else if (qname.equals("klass")) {
321 type(search(atts, "id"), search(atts, "name"));
322 } else if (qname.equals("method")) {
323 String id = search(atts, "id");
324 Method m = new Method();
325 m.setHolder(type(search(atts, "holder")));
326 m.setName(search(atts, "name"));
327 m.setReturnType(type(search(atts, "return")));
328 m.setArguments(search(atts, "arguments", "void"));
329
330 if (search(atts, "unloaded", "0").equals("0")) {
331 m.setBytes(search(atts, "bytes"));
332 m.setIICount(search(atts, "iicount"));
333 m.setFlags(search(atts, "flags"));
334 }
335 methods.put(id, m);
336 } else if (qname.equals("call")) {
337 if (methodHandleSite != null) {
338 methodHandleSite = null;
339 }
340 Method m = method(search(atts, "method"));
341 if (lateInlining && scopes.size() == 0) {
342 // re-attempting already seen call site (late inlining for MH invokes)
343 if (m != site.getMethod()) {
344 if (bci != site.getBci()) {
345 System.out.println(m + " bci: " + bci);
346 System.out.println(site.getMethod() + " bci: " + site.getBci());
347 throw new InternalError("bci mismatch after late inlining");
348 }
349 site.setMethod(m);
350 }
351 } else {
352 site = new CallSite(bci, m);
353 }
354 site.setCount(Integer.parseInt(search(atts, "count", "0")));
355 String receiver = atts.getValue("receiver");
356 if (receiver != null) {
357 site.setReceiver(type(receiver));
358 site.setReceiver_count(Integer.parseInt(search(atts, "receiver_count")));
359 }
360 int methodHandle = Integer.parseInt(search(atts, "method_handle_intrinsic", "0"));
361 if (lateInlining && scopes.size() == 0) {
362 // The call was added before this round of late inlining
363 } else if (methodHandle == 0) {
364 scopes.peek().add(site);
365 } else {
366 // method handle call site can be followed by another
367 // call (in case it is inlined). If that happens we
368 // discard the method handle call site. So we keep
369 // track of it but don't add it to the list yet.
370 methodHandleSite = site;
371 }
372 } else if (qname.equals("regalloc")) {
373 compile.setAttempts(Integer.parseInt(search(atts, "attempts")));
374 } else if (qname.equals("inline_fail")) {
375 if (methodHandleSite != null) {
376 scopes.peek().add(methodHandleSite);
377 methodHandleSite = null;
378 }
379 if (lateInlining && scopes.size() == 0) {
380 site.setReason(search(atts, "reason"));
381 lateInlining = false;
382 } else {
383 scopes.peek().last().setReason(search(atts, "reason"));
384 }
385 } else if (qname.equals("inline_success")) {
386 if (methodHandleSite != null) {
387 throw new InternalError("method handle site should have been replaced");
388 }
389 if (lateInlining && scopes.size() == 0) {
390 site.setReason(null);
391 }
392 } else if (qname.equals("failure")) {
393 failureReason = search(atts, "reason");
394 } else if (qname.equals("task_done")) {
395 compile.setEnd(Double.parseDouble(search(atts, "stamp")));
396 if (Integer.parseInt(search(atts, "success")) == 0) {
397 compile.setFailureReason(failureReason);
398 }
399 } else if (qname.equals("make_not_entrant")) {
400 String id = makeId(atts);
401 NMethod nm = nmethods.get(id);
402 if (nm == null) throw new InternalError();
403 LogEvent e = new MakeNotEntrantEvent(Double.parseDouble(search(atts, "stamp")), id,
404 atts.getValue("zombie") != null, nm);
405 events.add(e);
406 } else if (qname.equals("uncommon_trap")) {
407 String id = atts.getValue("compile_id");
408 if (id != null) {
409 id = makeId(atts);
410 currentTrap = new UncommonTrapEvent(Double.parseDouble(search(atts, "stamp")),
411 id,
412 atts.getValue("reason"),
413 atts.getValue("action"),
414 Integer.parseInt(search(atts, "count", "0")));
415 events.add(currentTrap);
416 } else {
417 // uncommon trap inserted during parsing.
418 // ignore for now
419 }
420 } else if (qname.equals("late_inline")) {
421 long inlineId = Long.parseLong(search(atts, "inline_id"));
422 lateInlineScope = new Stack<CallSite>();
423 site = new CallSite(-999, method(search(atts, "method")));
424 site.setInlineId(inlineId);
425 lateInlineScope.push(site);
426 } else if (qname.equals("jvms")) {
427 // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
428 if (currentTrap != null) {
429 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
430 } else if (lateInlineScope != null) {
431 bci = Integer.parseInt(search(atts, "bci"));
432 site = new CallSite(bci, method(search(atts, "method")));
433 lateInlineScope.push(site);
434 } else {
435 // Ignore <eliminate_allocation type='667'>,
436 // <eliminate_lock lock='1'>,
437 // <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
438 }
439 } else if (qname.equals("inline_id")) {
440 if (methodHandleSite != null) {
441 throw new InternalError("method handle site should have been replaced");
442 }
443 long id = Long.parseLong(search(atts, "id"));
444 site.setInlineId(id);
445 } else if (qname.equals("nmethod")) {
446 String id = makeId(atts);
447 NMethod nm = new NMethod(Double.parseDouble(search(atts, "stamp")),
448 id,
449 parseLong(atts.getValue("address")),
450 parseLong(atts.getValue("size")));
451 nmethods.put(id, nm);
452 events.add(nm);
453 } else if (qname.equals("parse")) {
454 if (methodHandleSite != null) {
455 throw new InternalError("method handle site should have been replaced");
456 }
457 Method m = method(search(atts, "method"));
458 if (lateInlining && scopes.size() == 0) {
459 if (site.getMethod() != m) {
460 System.out.println(site.getMethod());
461 System.out.println(m);
462 throw new InternalError("Unexpected method mismatch during late inlining");
463 }
464 }
465 if (scopes.size() == 0 && !lateInlining) {
466 compile.setMethod(m);
467 scopes.push(site);
468 } else {
469 if (site.getMethod() == m) {
470 scopes.push(site);
471 } else if (scopes.peek().getCalls().size() > 2 && m == scopes.peek().last(-2).getMethod()) {
472 scopes.push(scopes.peek().last(-2));
473 } else {
474 System.out.println(site.getMethod());
475 System.out.println(m);
476 throw new InternalError("call site and parse don't match");
477 }
478 }
479 } else if (qname.equals("parse_done")) {
480 CallSite call = scopes.pop();
481 call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0")));
482 call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0")));
483 call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
484 scopes.push(call);
485 }
486 }
487
488 @Override
489 public void endElement(String uri,
490 String localName,
491 String qname) {
492 if (qname.equals("parse")) {
493 indent -= 2;
494 scopes.pop();
495 if (scopes.size() == 0) {
496 lateInlining = false;
497 }
498 } else if (qname.equals("uncommon_trap")) {
499 currentTrap = null;
500 } else if (qname.equals("late_inline")) {
501 // Populate late inlining info.
502 if (scopes.size() != 0) {
503 throw new InternalError("scopes should be empty for late inline");
504 }
505 // late inline scopes are specified in reverse order:
506 // compiled method should be on top of stack.
507 CallSite caller = lateInlineScope.pop();
508 Method m = compile.getMethod();
509 if (m != caller.getMethod()) {
510 System.out.println(m);
511 System.out.println(caller.getMethod() + " bci: " + bci);
512 throw new InternalError("call site and late_inline info don't match");
513 }
514
515 // late_inline contains caller+bci info, convert it
516 // to bci+callee info used by LogCompilation.
517 CallSite lateInlineSite = compile.getLateInlineCall();
518 ArrayDeque<CallSite> thisCallScopes = new ArrayDeque<CallSite>();
519 do {
520 bci = caller.getBci();
521 // Next inlined call.
522 caller = lateInlineScope.pop();
523 CallSite callee = new CallSite(bci, caller.getMethod());
524 callee.setInlineId(caller.getInlineId());
525 thisCallScopes.addLast(callee);
526 lateInlineSite.add(callee);
527 lateInlineSite = callee;
528 } while (!lateInlineScope.empty());
529
530 site = compile.getCall().findCallSite(thisCallScopes);
531 if (site == null) {
532 System.out.println(caller.getMethod() + " bci: " + bci);
533 throw new InternalError("couldn't find call site");
534 }
535 lateInlining = true;
536
537 if (caller.getBci() != -999) {
538 System.out.println(caller.getMethod());
539 throw new InternalError("broken late_inline info");
540 }
541 if (site.getMethod() != caller.getMethod()) {
542 if (site.getInlineId() == caller.getInlineId()) {
543 site.setMethod(caller.getMethod());
544 } else {
545 System.out.println(site.getMethod());
546 System.out.println(caller.getMethod());
547 throw new InternalError("call site and late_inline info don't match");
548 }
549 }
550 // late_inline is followed by parse with scopes.size() == 0,
551 // 'site' will be pushed to scopes.
552 lateInlineScope = null;
553 } else if (qname.equals("task")) {
554 types.clear();
555 methods.clear();
556 site = null;
557 }
558 }
559
560 @Override
561 public void warning(org.xml.sax.SAXParseException e) {
562 System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
563 e.printStackTrace();
564 }
565
566 @Override
567 public void error(org.xml.sax.SAXParseException e) {
568 System.err.println(e.getMessage() + " at line " + e.getLineNumber() + ", column " + e.getColumnNumber());
569 e.printStackTrace();
570 }
571
572 @Override
|