1 /* 2 * Copyright 2002-2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.ui.classbrowser; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.asm.*; 30 import sun.jvm.hotspot.asm.sparc.*; 31 import sun.jvm.hotspot.asm.x86.*; 32 import sun.jvm.hotspot.asm.ia64.*; 33 import sun.jvm.hotspot.code.*; 34 import sun.jvm.hotspot.compiler.*; 35 import sun.jvm.hotspot.debugger.*; 36 import sun.jvm.hotspot.interpreter.*; 37 import sun.jvm.hotspot.memory.*; 38 import sun.jvm.hotspot.oops.*; 39 import sun.jvm.hotspot.runtime.*; 40 import sun.jvm.hotspot.tools.jcore.*; 41 import sun.jvm.hotspot.types.*; 42 import sun.jvm.hotspot.utilities.*; 43 44 public class HTMLGenerator implements /* imports */ ClassConstants { 45 static class Formatter { 46 boolean html; 47 StringBuffer buf = new StringBuffer(); 48 49 Formatter(boolean h) { 50 html = h; 51 } 52 53 void append(String s) { 54 buf.append(s); 55 } 56 57 void append(int s) { 58 buf.append(s); 59 } 60 61 void append(char s) { 62 buf.append(s); 63 } 64 65 void append(StringBuffer s) { 66 buf.append(s); 67 } 68 69 void append(Formatter s) { 70 buf.append(s); 71 } 72 73 StringBuffer getBuffer() { 74 return buf; 75 } 76 77 public String toString() { 78 return buf.toString(); 79 } 80 81 void wrap(String tag, String text) { 82 wrap(tag, tag, text); 83 } 84 void wrap(String before, String after, String text) { 85 beginTag(before); 86 append(text); 87 endTag(after); 88 } 89 90 // header tags 91 void h1(String s) { nl(); wrap("h1", s); nl(); } 92 void h2(String s) { nl(); wrap("h2", s); nl(); } 93 void h3(String s) { nl(); wrap("h3", s); nl(); } 94 void h4(String s) { nl(); wrap("h4", s); nl(); } 95 96 // list tags 97 void beginList() { beginTag("ul"); nl(); } 98 void li(String s) { wrap("li", s); nl(); } 99 void endList() { endTag("ul"); nl(); } 100 101 // table tags 102 void beginTable(int border) { 103 beginTag("table border='" + border + "'"); 104 } 105 void cell(String s) { wrap("td", s); } 106 void headerCell(String s) { wrap("th", s); } 107 void endTable() { endTag("table"); } 108 109 void link(String href, String text) { 110 wrap("a href='" + href + "'", "a", text); 111 } 112 void beginTag(String s) { 113 if (html) { append("<"); append(s); append(">"); } 114 } 115 void endTag(String s) { 116 if (html) { 117 append("</"); append(s); append(">"); 118 } else { 119 if (s.equals("table") || s.equals("tr")) { 120 nl(); 121 } 122 if (s.equals("td") || s.equals("th")) { 123 append(" "); 124 } 125 } 126 } 127 void bold(String s) { 128 wrap("b", s); 129 } 130 131 void nl() { 132 if (!html) buf.append("\n"); 133 } 134 135 void br() { 136 if (html) append("<br>"); 137 else append("\n"); 138 } 139 void genEmptyHTML() { 140 if (html) append("<html></html>"); 141 } 142 143 void genHTMLPrologue() { 144 if (html) append("<html><body>"); 145 } 146 147 void genHTMLPrologue(String title) { 148 if (html) { 149 append("<html><head><title>"); 150 append(title); 151 append("</title></head>"); 152 append("<body>"); 153 } 154 h2(title); 155 } 156 void genHTMLEpilogue() { 157 if (html) append("</body></html>"); 158 } 159 160 } 161 162 private static final String DUMP_KLASS_OUTPUT_DIR = "."; 163 private static final int NATIVE_CODE_SIZE = 200; 164 private final String spaces; 165 private final String tab; 166 167 private boolean genHTML = true; 168 169 public HTMLGenerator() { 170 this(true); 171 } 172 173 public HTMLGenerator(boolean html) { 174 genHTML = html; 175 if (html) { 176 spaces = " "; 177 tab = " "; 178 } else { 179 spaces = " "; 180 tab = " "; 181 } 182 } 183 184 private static CPUHelper cpuHelper; 185 static { 186 VM.registerVMInitializedObserver(new Observer() { 187 public void update(Observable o, Object data) { 188 initialize(); 189 } 190 }); 191 } 192 193 private static synchronized void initialize() { 194 String cpu = VM.getVM().getCPU(); 195 if (cpu.equals("sparc")) { 196 cpuHelper = new SPARCHelper(); 197 } else if (cpu.equals("x86")) { 198 cpuHelper = new X86Helper(); 199 } else if (cpu.equals("ia64")) { 200 cpuHelper = new IA64Helper(); 201 } else { 202 throw new RuntimeException("cpu '" + cpu + "' is not yet supported!"); 203 } 204 } 205 206 protected static synchronized CPUHelper getCPUHelper() { 207 return cpuHelper; 208 } 209 210 protected String escapeHTMLSpecialChars(String value) { 211 if (!genHTML) return value; 212 213 Formatter buf = new Formatter(genHTML); 214 int len = value.length(); 215 for (int i=0; i < len; i++) { 216 char c = value.charAt(i); 217 switch (c) { 218 case '<': 219 buf.append("<"); 220 break; 221 case '>': 222 buf.append(">"); 223 break; 224 case '&': 225 buf.append("&"); 226 break; 227 default: 228 buf.append(c); 229 break; 230 } 231 } 232 return buf.toString(); 233 } 234 235 public String genHTMLForMessage(String message) { 236 Formatter buf = new Formatter(genHTML); 237 buf.genHTMLPrologue(message); 238 buf.genHTMLEpilogue(); 239 return buf.toString(); 240 } 241 242 public String genHTMLErrorMessage(Exception exp) { 243 exp.printStackTrace(); 244 return genHTMLForMessage(exp.getClass().getName() + " : " + exp.getMessage()); 245 } 246 247 public String genHTMLForWait(String message) { 248 Formatter buf = new Formatter(genHTML); 249 buf.genHTMLPrologue("Please wait .."); 250 buf.h2(message); 251 return buf.toString(); 252 } 253 254 protected String genKlassTitle(InstanceKlass klass) { 255 Formatter buf = new Formatter(genHTML); 256 AccessFlags acc = klass.getAccessFlagsObj(); 257 if (acc.isPublic()) { 258 buf.append("public "); 259 } else if (acc.isProtected()) { 260 buf.append("protected "); 261 } else if (acc.isPrivate()) { 262 buf.append("private "); 263 } 264 265 if (acc.isStatic()) { 266 buf.append("static "); 267 } 268 269 if (acc.isAbstract() ) { 270 buf.append("abstract "); 271 } else if (acc.isFinal()) { 272 buf.append("final "); 273 } 274 275 if (acc.isStrict()) { 276 buf.append("strict "); 277 } 278 279 // javac generated flags 280 if (acc.isEnum()) { 281 buf.append("[enum] "); 282 } 283 if (acc.isSynthetic()) { 284 buf.append("[synthetic] "); 285 } 286 287 if (klass.isInterface()) { 288 buf.append("interface"); 289 } else { 290 buf.append("class"); 291 } 292 293 buf.append(' '); 294 buf.append(klass.getName().asString().replace('/', '.')); 295 // is it generic? 296 Symbol genSig = klass.getGenericSignature(); 297 if (genSig != null) { 298 buf.append(" [signature "); 299 buf.append(escapeHTMLSpecialChars(genSig.asString())); 300 buf.append("] "); 301 } else { 302 buf.append(' '); 303 } 304 buf.append('@'); 305 buf.append(klass.getHandle().toString()); 306 return buf.toString(); 307 } 308 309 protected String genBaseHref() { 310 return ""; 311 } 312 313 protected String genKlassHref(InstanceKlass klass) { 314 return genBaseHref() + "klass=" + klass.getHandle(); 315 } 316 317 protected String genKlassLink(InstanceKlass klass) { 318 Formatter buf = new Formatter(genHTML); 319 buf.link(genKlassHref(klass), genKlassTitle(klass)); 320 return buf.toString(); 321 } 322 323 protected String genMethodModifierString(AccessFlags acc) { 324 Formatter buf = new Formatter(genHTML); 325 if (acc.isPrivate()) { 326 buf.append("private "); 327 } else if (acc.isProtected()) { 328 buf.append("protected "); 329 } else if (acc.isPublic()) { 330 buf.append("public "); 331 } 332 333 if (acc.isStatic()) { 334 buf.append("static "); 335 } else if (acc.isAbstract() ) { 336 buf.append("abstract "); 337 } else if (acc.isFinal()) { 338 buf.append("final "); 339 } 340 341 if (acc.isNative()) { 342 buf.append("native "); 343 } 344 345 if (acc.isStrict()) { 346 buf.append("strict "); 347 } 348 349 if (acc.isSynchronized()) { 350 buf.append("synchronized "); 351 } 352 353 // javac generated flags 354 if (acc.isBridge()) { 355 buf.append("[bridge] "); 356 } 357 358 if (acc.isSynthetic()) { 359 buf.append("[synthetic] "); 360 } 361 362 if (acc.isVarArgs()) { 363 buf.append("[varargs] "); 364 } 365 366 return buf.toString(); 367 } 368 369 protected String genMethodNameAndSignature(Method method) { 370 Formatter buf = new Formatter(genHTML); 371 buf.append(genMethodModifierString(method.getAccessFlagsObj())); 372 Symbol sig = method.getSignature(); 373 new SignatureConverter(sig, buf.getBuffer()).iterateReturntype(); 374 buf.append(" "); 375 String methodName = method.getName().asString(); 376 buf.append(escapeHTMLSpecialChars(methodName)); 377 buf.append('('); 378 new SignatureConverter(sig, buf.getBuffer()).iterateParameters(); 379 buf.append(')'); 380 // is it generic? 381 Symbol genSig = method.getGenericSignature(); 382 if (genSig != null) { 383 buf.append(" [signature "); 384 buf.append(escapeHTMLSpecialChars(genSig.asString())); 385 buf.append("] "); 386 } 387 return buf.toString().replace('/', '.'); 388 } 389 390 protected String genMethodTitle(Method method) { 391 Formatter buf = new Formatter(genHTML); 392 buf.append(genMethodNameAndSignature(method)); 393 buf.append(' '); 394 buf.append('@'); 395 buf.append(method.getHandle().toString()); 396 return buf.toString(); 397 } 398 399 protected String genMethodHref(Method m) { 400 return genBaseHref() + "method=" + m.getHandle(); 401 } 402 403 protected String genMethodLink(Method m) { 404 Formatter buf = new Formatter(genHTML); 405 buf.link(genMethodHref(m), genMethodTitle(m)); 406 return buf.toString(); 407 } 408 409 protected String genMethodAndKlassLink(Method m) { 410 Formatter buf = new Formatter(genHTML); 411 buf.append(genMethodLink(m)); 412 buf.append(" of "); 413 buf.append(genKlassLink((InstanceKlass) m.getMethodHolder())); 414 return buf.toString(); 415 } 416 417 protected String genNMethodHref(NMethod nm) { 418 return genBaseHref() + "nmethod=" + nm.getAddress(); 419 } 420 421 public String genNMethodTitle(NMethod nmethod) { 422 Formatter buf = new Formatter(genHTML); 423 Method m = nmethod.getMethod(); 424 425 buf.append("Disassembly for compiled method ["); 426 buf.append(genMethodTitle(m)); 427 buf.append(" ] "); 428 buf.append('@'); 429 buf.append(nmethod.getAddress().toString()); 430 return buf.toString(); 431 } 432 433 protected String genNMethodLink(NMethod nm) { 434 Formatter buf = new Formatter(genHTML); 435 buf.link(genNMethodHref(nm), genNMethodTitle(nm)); 436 return buf.toString(); 437 } 438 439 public String genCodeBlobTitle(CodeBlob blob) { 440 Formatter buf = new Formatter(genHTML); 441 buf.append("Disassembly for code blob " + blob.getName() + " ["); 442 buf.append(blob.getClass().getName()); 443 buf.append(" ] @"); 444 buf.append(blob.getAddress().toString()); 445 return buf.toString(); 446 } 447 448 protected BytecodeDisassembler createBytecodeDisassembler(Method m) { 449 return new BytecodeDisassembler(m); 450 } 451 452 private String genLowHighShort(int val) { 453 Formatter buf = new Formatter(genHTML); 454 buf.append('#'); 455 buf.append(Integer.toString(val & 0xFFFF)); 456 buf.append(" #"); 457 buf.append(Integer.toString((val >> 16) & 0xFFFF)); 458 return buf.toString(); 459 } 460 461 protected String genHTMLTableForConstantPool(ConstantPool cpool) { 462 Formatter buf = new Formatter(genHTML); 463 buf.beginTable(1); 464 465 buf.beginTag("tr"); 466 buf.headerCell("Index"); 467 buf.headerCell("Constant Type"); 468 buf.headerCell("Constant Value"); 469 buf.endTag("tr"); 470 471 final int length = (int) cpool.getLength(); 472 // zero'th pool entry is always invalid. ignore it. 473 for (int index = 1; index < length; index++) { 474 buf.beginTag("tr"); 475 buf.cell(Integer.toString(index)); 476 477 int ctag = (int) cpool.getTags().getByteAt((int) index); 478 switch (ctag) { 479 case JVM_CONSTANT_Integer: 480 buf.cell("JVM_CONSTANT_Integer"); 481 buf.cell(Integer.toString(cpool.getIntAt(index))); 482 break; 483 484 case JVM_CONSTANT_Float: 485 buf.cell("JVM_CONSTANT_Float"); 486 buf.cell(Float.toString(cpool.getFloatAt(index))); 487 break; 488 489 case JVM_CONSTANT_Long: 490 buf.cell("JVM_CONSTANT_Long"); 491 buf.cell(Long.toString(cpool.getLongAt(index))); 492 // long entries occupy two slots 493 index++; 494 break; 495 496 case JVM_CONSTANT_Double: 497 buf.cell("JVM_CONSTANT_Double"); 498 buf.cell(Double.toString(cpool.getDoubleAt(index))); 499 // double entries occupy two slots 500 index++; 501 break; 502 503 case JVM_CONSTANT_UnresolvedClass: 504 buf.cell("JVM_CONSTANT_UnresolvedClass"); 505 buf.cell(cpool.getSymbolAt(index).asString()); 506 break; 507 508 case JVM_CONSTANT_Class: 509 buf.cell("JVM_CONSTANT_Class"); 510 Klass klass = (Klass) cpool.getObjAt(index); 511 if (klass instanceof InstanceKlass) { 512 buf.cell(genKlassLink((InstanceKlass) klass)); 513 } else { 514 buf.cell(klass.getName().asString().replace('/', '.')); 515 } 516 break; 517 518 case JVM_CONSTANT_UnresolvedString: 519 buf.cell("JVM_CONSTANT_UnresolvedString"); 520 buf.cell("\"" + 521 escapeHTMLSpecialChars(cpool.getSymbolAt(index).asString()) + 522 "\""); 523 break; 524 525 case JVM_CONSTANT_Utf8: 526 buf.cell("JVM_CONSTANT_Utf8"); 527 buf.cell("\"" + 528 escapeHTMLSpecialChars(cpool.getSymbolAt(index).asString()) + 529 "\""); 530 break; 531 532 case JVM_CONSTANT_String: 533 buf.cell("JVM_CONSTANT_String"); 534 buf.cell("\"" + 535 escapeHTMLSpecialChars(OopUtilities.stringOopToString(cpool.getObjAt(index))) + "\""); 536 break; 537 538 case JVM_CONSTANT_Fieldref: 539 buf.cell("JVM_CONSTANT_Fieldref"); 540 buf.cell(genLowHighShort(cpool.getIntAt(index))); 541 break; 542 543 case JVM_CONSTANT_Methodref: 544 buf.cell("JVM_CONSTANT_Methodref"); 545 buf.cell(genLowHighShort(cpool.getIntAt(index))); 546 break; 547 548 case JVM_CONSTANT_InterfaceMethodref: 549 buf.cell("JVM_CONSTANT_InterfaceMethodref"); 550 buf.cell(genLowHighShort(cpool.getIntAt(index))); 551 break; 552 553 case JVM_CONSTANT_NameAndType: 554 buf.cell("JVM_CONSTANT_NameAndType"); 555 buf.cell(genLowHighShort(cpool.getIntAt(index))); 556 break; 557 558 case JVM_CONSTANT_ClassIndex: 559 buf.cell("JVM_CONSTANT_ClassIndex"); 560 buf.cell(Integer.toString(cpool.getIntAt(index))); 561 break; 562 563 case JVM_CONSTANT_StringIndex: 564 buf.cell("JVM_CONSTANT_StringIndex"); 565 buf.cell(Integer.toString(cpool.getIntAt(index))); 566 break; 567 } 568 569 buf.endTag("tr"); 570 } 571 572 buf.endTable(); 573 return buf.toString(); 574 } 575 576 public String genHTML(ConstantPool cpool) { 577 try { 578 Formatter buf = new Formatter(genHTML); 579 buf.genHTMLPrologue(genConstantPoolTitle(cpool)); 580 buf.h3("Holder Class"); 581 buf.append(genKlassLink((InstanceKlass) cpool.getPoolHolder())); 582 buf.h3("Constants"); 583 buf.append(genHTMLTableForConstantPool(cpool)); 584 buf.genHTMLEpilogue(); 585 return buf.toString(); 586 } catch (Exception exp) { 587 return genHTMLErrorMessage(exp); 588 } 589 } 590 591 protected String genConstantPoolHref(ConstantPool cpool) { 592 return genBaseHref() + "cpool=" + cpool.getHandle(); 593 } 594 595 protected String genConstantPoolTitle(ConstantPool cpool) { 596 Formatter buf = new Formatter(genHTML); 597 buf.append("Constant Pool of ["); 598 buf.append(genKlassTitle((InstanceKlass) cpool.getPoolHolder())); 599 buf.append("] @"); 600 buf.append(cpool.getHandle().toString()); 601 return buf.toString(); 602 } 603 604 protected String genConstantPoolLink(ConstantPool cpool) { 605 Formatter buf = new Formatter(genHTML); 606 buf.link(genConstantPoolHref(cpool), genConstantPoolTitle(cpool)); 607 return buf.toString(); 608 } 609 610 public String genHTML(Method method) { 611 try { 612 final Formatter buf = new Formatter(genHTML); 613 buf.genHTMLPrologue(genMethodTitle(method)); 614 615 buf.h3("Holder Class"); 616 buf.append(genKlassLink((InstanceKlass) method.getMethodHolder())); 617 618 NMethod nmethod = method.getNativeMethod(); 619 if (nmethod != null) { 620 buf.h3("Compiled Code"); 621 buf.append(genNMethodLink(nmethod)); 622 } 623 624 boolean hasThrows = method.hasCheckedExceptions(); 625 ConstantPool cpool = ((InstanceKlass) method.getMethodHolder()).getConstants(); 626 if (hasThrows) { 627 buf.h3("Checked Exception(s)"); 628 CheckedExceptionElement[] exceptions = method.getCheckedExceptions(); 629 buf.beginTag("ul"); 630 for (int exp = 0; exp < exceptions.length; exp++) { 631 short cpIndex = (short) exceptions[exp].getClassCPIndex(); 632 Oop obj = cpool.getObjAt(cpIndex); 633 if (obj instanceof Symbol) { 634 buf.li(((Symbol)obj).asString().replace('/', '.')); 635 } else { 636 buf.li(genKlassLink((InstanceKlass)obj)); 637 } 638 } 639 buf.endTag("ul"); 640 } 641 642 if (method.isNative() || method.isAbstract()) { 643 buf.genHTMLEpilogue(); 644 return buf.toString(); 645 } 646 647 buf.h3("Bytecode"); 648 BytecodeDisassembler disasm = createBytecodeDisassembler(method); 649 final boolean hasLineNumbers = method.hasLineNumberTable(); 650 disasm.decode(new BytecodeVisitor() { 651 private Method method; 652 public void prologue(Method m) { 653 method = m; 654 buf.beginTable(0); 655 buf.beginTag("tr"); 656 if (hasLineNumbers) { 657 buf.headerCell("line"); 658 } 659 buf.headerCell("bci" + spaces); 660 buf.headerCell("bytecode"); 661 buf.endTag("tr"); 662 } 663 664 public void visit(Bytecode instr) { 665 int curBci = instr.bci(); 666 buf.beginTag("tr"); 667 if (hasLineNumbers) { 668 int lineNumber = method.getLineNumberFromBCI(curBci); 669 buf.cell(Integer.toString(lineNumber) + spaces); 670 } 671 buf.cell(Integer.toString(curBci) + spaces); 672 673 buf.beginTag("td"); 674 String instrStr = escapeHTMLSpecialChars(instr.toString()); 675 676 if (instr instanceof BytecodeNew) { 677 BytecodeNew newBytecode = (BytecodeNew) instr; 678 InstanceKlass klass = newBytecode.getNewKlass(); 679 if (klass != null) { 680 buf.link(genKlassHref(klass), instrStr); 681 } else { 682 buf.append(instrStr); 683 } 684 } else if(instr instanceof BytecodeInvoke) { 685 BytecodeInvoke invokeBytecode = (BytecodeInvoke) instr; 686 Method m = invokeBytecode.getInvokedMethod(); 687 if (m != null) { 688 buf.link(genMethodHref(m), instrStr); 689 buf.append(" of "); 690 InstanceKlass klass = (InstanceKlass) m.getMethodHolder(); 691 buf.link(genKlassHref(klass), genKlassTitle(klass)); 692 } else { 693 buf.append(instrStr); 694 } 695 } else if (instr instanceof BytecodeGetPut) { 696 BytecodeGetPut getPut = (BytecodeGetPut) instr; 697 sun.jvm.hotspot.oops.Field f = getPut.getField(); 698 buf.append(instrStr); 699 if (f != null) { 700 InstanceKlass klass = f.getFieldHolder(); 701 buf.append(" of "); 702 buf.link(genKlassHref(klass), genKlassTitle(klass)); 703 } 704 } else if (instr instanceof BytecodeLoadConstant) { 705 BytecodeLoadConstant ldc = (BytecodeLoadConstant) instr; 706 if (ldc.isKlassConstant()) { 707 Oop oop = ldc.getKlass(); 708 if (oop instanceof Klass) { 709 buf.append("<a href='"); 710 buf.append(genKlassHref((InstanceKlass) oop)); 711 buf.append("'>"); 712 buf.append(instrStr); 713 buf.append("</a>"); 714 } else { 715 // unresolved klass literal 716 buf.append(instrStr); 717 } 718 } else { 719 // not a klass literal 720 buf.append(instrStr); 721 } 722 } else { 723 buf.append(instrStr); 724 } 725 buf.endTag("td"); 726 buf.endTag("tr"); 727 } 728 729 public void epilogue() { 730 buf.endTable(); 731 } 732 }); 733 734 // display exception table for this method 735 TypeArray exceptionTable = method.getExceptionTable(); 736 // exception table is 4 tuple array of shorts 737 int numEntries = (int)exceptionTable.getLength() / 4; 738 if (numEntries != 0) { 739 buf.h4("Exception Table"); 740 buf.beginTable(1); 741 buf.beginTag("tr"); 742 buf.headerCell("start bci"); 743 buf.headerCell("end bci"); 744 buf.headerCell("handler bci"); 745 buf.headerCell("catch type"); 746 buf.endTag("tr"); 747 748 for (int e = 0; e < numEntries; e += 4) { 749 buf.beginTag("tr"); 750 buf.cell(Integer.toString(exceptionTable.getIntAt(e))); 751 buf.cell(Integer.toString(exceptionTable.getIntAt(e + 1))); 752 buf.cell(Integer.toString(exceptionTable.getIntAt(e + 2))); 753 short cpIndex = (short) exceptionTable.getIntAt(e + 3); 754 Oop obj = cpIndex == 0? null : cpool.getObjAt(cpIndex); 755 if (obj == null) { 756 buf.cell("Any"); 757 } else if (obj instanceof Symbol) { 758 buf.cell(((Symbol)obj).asString().replace('/', '.')); 759 } else { 760 buf.cell(genKlassLink((InstanceKlass)obj)); 761 } 762 buf.endTag("tr"); 763 } 764 765 buf.endTable(); 766 } 767 768 // display constant pool hyperlink 769 buf.h3("Constant Pool"); 770 buf.append(genConstantPoolLink(cpool)); 771 buf.genHTMLEpilogue(); 772 return buf.toString(); 773 } catch (Exception exp) { 774 return genHTMLErrorMessage(exp); 775 } 776 } 777 778 protected Disassembler createDisassembler(long startPc, byte[] code) { 779 return getCPUHelper().createDisassembler(startPc, code); 780 } 781 782 protected SymbolFinder createSymbolFinder() { 783 return new DummySymbolFinder(); 784 } 785 786 // genHTML for a given address. Address may be a PC or 787 // methodOop or klassOop. 788 789 public String genHTMLForAddress(String addrStr) { 790 return genHTML(parseAddress(addrStr)); 791 } 792 793 public String genHTML(sun.jvm.hotspot.debugger.Address pc) { 794 CodeBlob blob = null; 795 796 try { 797 blob = (CodeBlob)VM.getVM().getCodeCache().findBlobUnsafe(pc); 798 } catch (Exception exp) { 799 // ignore 800 } 801 802 if (blob != null) { 803 if (blob instanceof NMethod) { 804 return genHTML((NMethod)blob); 805 } else { 806 // may be interpreter code. 807 Interpreter interp = VM.getVM().getInterpreter(); 808 if (interp.contains(pc)) { 809 InterpreterCodelet codelet = interp.getCodeletContaining(pc); 810 if (codelet == null) { 811 return "Unknown location in the Interpreter: " + pc; 812 } 813 return genHTML(codelet); 814 } 815 return genHTML(blob); 816 } 817 } else if (VM.getVM().getCodeCache().contains(pc)) { 818 return "Unknown location in the CodeCache: " + pc; 819 } 820 821 // did not find nmethod. 822 // try methodOop, klassOop and constantPoolOop. 823 try { 824 Oop obj = getOopAtAddress(pc); 825 if (obj != null) { 826 if (obj instanceof Method) { 827 return genHTML((Method) obj); 828 } else if (obj instanceof InstanceKlass) { 829 return genHTML((InstanceKlass) obj); 830 } else if (obj instanceof ConstantPool) { 831 return genHTML((ConstantPool) obj); 832 } 833 } 834 } catch (Exception exp) { 835 // ignore 836 } 837 838 // didn't find any. do raw disassembly. 839 return genHTMLForRawDisassembly(pc, null); 840 } 841 842 protected byte[] readBuffer(sun.jvm.hotspot.debugger.Address addr, int size) { 843 byte[] buf = new byte[size]; 844 for (int b = 0; b < size; b++) { 845 buf[b] = (byte) addr.getJByteAt(b); 846 } 847 return buf; 848 } 849 850 public String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc, int size) { 851 try { 852 return genHTMLForRawDisassembly(startPc, null, readBuffer(startPc, size)); 853 } catch (Exception exp) { 854 return genHTMLErrorMessage(exp); 855 } 856 } 857 858 protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc, 859 String prevPCs) { 860 try { 861 return genHTMLForRawDisassembly(startPc, prevPCs, readBuffer(startPc, NATIVE_CODE_SIZE)); 862 } catch (Exception exp) { 863 return genHTMLErrorMessage(exp); 864 } 865 } 866 867 protected String genPCHref(long targetPc) { 868 return genBaseHref() + "pc=0x" + Long.toHexString(targetPc); 869 } 870 871 protected String genMultPCHref(String pcs) { 872 StringBuffer buf = new StringBuffer(genBaseHref()); 873 buf.append("pc_multiple="); 874 buf.append(pcs); 875 return buf.toString(); 876 } 877 878 protected String genPCHref(long currentPc, sun.jvm.hotspot.asm.Address addr) { 879 String href = null; 880 if (addr instanceof PCRelativeAddress) { 881 PCRelativeAddress pcRelAddr = (PCRelativeAddress) addr; 882 href = genPCHref(currentPc + pcRelAddr.getDisplacement()); 883 } else if(addr instanceof DirectAddress) { 884 href = genPCHref(((DirectAddress) addr).getValue()); 885 } 886 887 return href; 888 } 889 890 class RawCodeVisitor implements InstructionVisitor { 891 private int instrSize = 0; 892 private Formatter buf; 893 private SymbolFinder symFinder = createSymbolFinder(); 894 895 RawCodeVisitor(Formatter buf) { 896 this.buf = buf; 897 } 898 899 public int getInstructionSize() { 900 return instrSize; 901 } 902 903 public void prologue() { 904 } 905 906 public void visit(long currentPc, Instruction instr) { 907 String href = null; 908 if (instr.isCall()) { 909 CallInstruction call = (CallInstruction) instr; 910 sun.jvm.hotspot.asm.Address addr = call.getBranchDestination(); 911 href = genPCHref(currentPc, addr); 912 } 913 914 instrSize += instr.getSize(); 915 buf.append("0x"); 916 buf.append(Long.toHexString(currentPc)); 917 buf.append(':'); 918 buf.append(tab); 919 920 if (href != null) { 921 buf.link(href, instr.asString(currentPc, symFinder)); 922 } else { 923 buf.append(instr.asString(currentPc, symFinder)); 924 } 925 buf.br(); 926 } 927 928 public void epilogue() { 929 } 930 }; 931 932 protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address addr, 933 String prevPCs, 934 byte[] code) { 935 try { 936 long startPc = addressToLong(addr); 937 Disassembler disasm = createDisassembler(startPc, code); 938 final Formatter buf = new Formatter(genHTML); 939 buf.genHTMLPrologue("Disassembly @0x" + Long.toHexString(startPc)); 940 941 if (prevPCs != null && genHTML) { 942 buf.beginTag("p"); 943 buf.link(genMultPCHref(prevPCs), "show previous code .."); 944 buf.endTag("p"); 945 } 946 947 948 buf.h3("Code"); 949 RawCodeVisitor visitor = new RawCodeVisitor(buf); 950 disasm.decode(visitor); 951 952 if (genHTML) buf.beginTag("p"); 953 Formatter tmpBuf = new Formatter(genHTML); 954 tmpBuf.append("0x"); 955 tmpBuf.append(Long.toHexString(startPc + visitor.getInstructionSize()).toString()); 956 tmpBuf.append(",0x"); 957 tmpBuf.append(Long.toHexString(startPc)); 958 if (prevPCs != null) { 959 tmpBuf.append(','); 960 tmpBuf.append(prevPCs); 961 } 962 if (genHTML) { 963 buf.link(genMultPCHref(tmpBuf.toString()), "show more code .."); 964 buf.endTag("p"); 965 } 966 967 buf.genHTMLEpilogue(); 968 return buf.toString(); 969 } catch (Exception exp) { 970 return genHTMLErrorMessage(exp); 971 } 972 } 973 974 protected String genSafepointInfo(NMethod nm, PCDesc pcDesc) { 975 ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm)); 976 Formatter buf = new Formatter(genHTML); 977 Formatter tabs = new Formatter(genHTML); 978 tabs.append(tab + tab + tab); // Initial indent for debug info 979 980 buf.beginTag("pre"); 981 genScope(buf, tabs, sd); 982 983 // Reset indent for scalar replaced objects 984 tabs = new Formatter(genHTML); 985 tabs.append(tab + tab + tab); // Initial indent for debug info 986 987 genScObjInfo(buf, tabs, sd); 988 buf.endTag("pre"); 989 990 buf.append(genOopMapInfo(nm, pcDesc)); 991 992 return buf.toString(); 993 } 994 995 protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) { 996 if (sd == null) { 997 return; 998 } 999 1000 genScope(buf, tabs, sd.sender()); 1001 1002 buf.append(tabs); 1003 Method m = sd.getMethod(); 1004 buf.append(genMethodAndKlassLink(m)); 1005 int bci = sd.getBCI(); 1006 buf.append(" @ bci = "); 1007 buf.append(Integer.toString(bci)); 1008 1009 int line = m.getLineNumberFromBCI(bci); 1010 if (line != -1) { 1011 buf.append(", line = "); 1012 buf.append(Integer.toString(line)); 1013 } 1014 1015 List locals = sd.getLocals(); 1016 if (locals != null) { 1017 buf.br(); 1018 buf.append(tabs); 1019 buf.append(genHTMLForLocals(sd, locals)); 1020 } 1021 1022 List expressions = sd.getExpressions(); 1023 if (expressions != null) { 1024 buf.br(); 1025 buf.append(tabs); 1026 buf.append(genHTMLForExpressions(sd, expressions)); 1027 } 1028 1029 List monitors = sd.getMonitors(); 1030 if (monitors != null) { 1031 buf.br(); 1032 buf.append(tabs); 1033 buf.append(genHTMLForMonitors(sd, monitors)); 1034 } 1035 1036 buf.br(); 1037 tabs.append(tab); 1038 } 1039 1040 protected void genScObjInfo(Formatter buf, Formatter tabs, ScopeDesc sd) { 1041 if (sd == null) { 1042 return; 1043 } 1044 1045 List objects = sd.getObjects(); 1046 if (objects == null) { 1047 return; 1048 } 1049 int length = objects.size(); 1050 for (int i = 0; i < length; i++) { 1051 buf.append(tabs); 1052 ObjectValue ov = (ObjectValue)objects.get(i); 1053 buf.append("ScObj" + i); 1054 ScopeValue sv = ov.getKlass(); 1055 if (Assert.ASSERTS_ENABLED) { 1056 Assert.that(sv.isConstantOop(), "scalar replaced object klass must be constant oop"); 1057 } 1058 ConstantOopReadValue klv = (ConstantOopReadValue)sv; 1059 OopHandle klHandle = klv.getValue(); 1060 if (Assert.ASSERTS_ENABLED) { 1061 Assert.that(klHandle != null, "scalar replaced object klass must be not NULL"); 1062 } 1063 Oop obj = VM.getVM().getObjectHeap().newOop(klHandle); 1064 if (obj instanceof InstanceKlass) { 1065 InstanceKlass kls = (InstanceKlass) obj; 1066 buf.append(" " + kls.getName().asString() + "={"); 1067 int flen = ov.fieldsSize(); 1068 1069 TypeArray klfields = kls.getFields(); 1070 int klen = (int) klfields.getLength(); 1071 1072 ConstantPool cp = kls.getConstants(); 1073 int findex = 0; 1074 for (int index = 0; index < klen; index += kls.NEXT_OFFSET) { 1075 int accsFlags = klfields.getShortAt(index + kls.ACCESS_FLAGS_OFFSET); 1076 int nameIndex = klfields.getShortAt(index + kls.NAME_INDEX_OFFSET); 1077 AccessFlags access = new AccessFlags(accsFlags); 1078 if (!access.isStatic()) { 1079 ScopeValue svf = ov.getFieldAt(findex++); 1080 String fstr = scopeValueAsString(sd, svf); 1081 Symbol f_name = cp.getSymbolAt(nameIndex); 1082 buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")"); 1083 } 1084 } 1085 buf.append(" }"); 1086 } else { 1087 buf.append(" "); 1088 int flen = ov.fieldsSize(); 1089 if (obj instanceof TypeArrayKlass) { 1090 TypeArrayKlass kls = (TypeArrayKlass) obj; 1091 buf.append(kls.getElementTypeName() + "[" + flen + "]"); 1092 } else if (obj instanceof ObjArrayKlass) { 1093 ObjArrayKlass kls = (ObjArrayKlass) obj; 1094 Klass elobj = kls.getBottomKlass(); 1095 if (elobj instanceof InstanceKlass) { 1096 buf.append(elobj.getName().asString()); 1097 } else if (elobj instanceof TypeArrayKlass) { 1098 TypeArrayKlass elkls = (TypeArrayKlass) elobj; 1099 buf.append(elkls.getElementTypeName()); 1100 } else { 1101 if (Assert.ASSERTS_ENABLED) { 1102 Assert.that(false, "unknown scalar replaced object klass!"); 1103 } 1104 } 1105 buf.append("[" + flen + "]"); 1106 int ndim = (int) kls.getDimension(); 1107 while (--ndim > 0) { 1108 buf.append("[]"); 1109 } 1110 } else { 1111 if (Assert.ASSERTS_ENABLED) { 1112 Assert.that(false, "unknown scalar replaced object klass!"); 1113 } 1114 } 1115 buf.append("={"); 1116 for (int findex = 0; findex < flen; findex++) { 1117 ScopeValue svf = ov.getFieldAt(findex); 1118 String fstr = scopeValueAsString(sd, svf); 1119 buf.append(" [" + findex + "]=(#" + fstr + ")"); 1120 } 1121 buf.append(" }"); 1122 } 1123 buf.br(); 1124 } 1125 } 1126 1127 protected String genHTMLForOopMap(OopMap map) { 1128 final int stack0 = VMRegImpl.getStack0().getValue(); 1129 Formatter buf = new Formatter(genHTML); 1130 1131 final class OopMapValueIterator { 1132 final Formatter iterate(OopMapStream oms, String type, boolean printContentReg) { 1133 Formatter tmpBuf = new Formatter(genHTML); 1134 boolean found = false; 1135 tmpBuf.beginTag("tr"); 1136 tmpBuf.beginTag("td"); 1137 tmpBuf.append(type); 1138 for (; ! oms.isDone(); oms.next()) { 1139 OopMapValue omv = oms.getCurrent(); 1140 if (omv == null) { 1141 continue; 1142 } 1143 found = true; 1144 VMReg vmReg = omv.getReg(); 1145 int reg = vmReg.getValue(); 1146 if (reg < stack0) { 1147 tmpBuf.append(VMRegImpl.getRegisterName(reg)); 1148 } else { 1149 tmpBuf.append('['); 1150 tmpBuf.append(Integer.toString((reg - stack0) * 4)); 1151 tmpBuf.append(']'); 1152 } 1153 if (printContentReg) { 1154 tmpBuf.append(" = "); 1155 VMReg vmContentReg = omv.getContentReg(); 1156 int contentReg = vmContentReg.getValue(); 1157 if (contentReg < stack0) { 1158 tmpBuf.append(VMRegImpl.getRegisterName(contentReg)); 1159 } else { 1160 tmpBuf.append('['); 1161 tmpBuf.append(Integer.toString((contentReg - stack0) * 4)); 1162 tmpBuf.append(']'); 1163 } 1164 } 1165 tmpBuf.append(spaces); 1166 } 1167 tmpBuf.endTag("td"); 1168 tmpBuf.endTag("tr"); 1169 return found ? tmpBuf : new Formatter(genHTML); 1170 } 1171 } 1172 1173 buf.beginTable(0); 1174 1175 OopMapValueIterator omvIterator = new OopMapValueIterator(); 1176 OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE); 1177 buf.append(omvIterator.iterate(oms, "Oops:", false)); 1178 1179 oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE); 1180 buf.append(omvIterator.iterate(oms, "narrowOops:", false)); 1181 1182 oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE); 1183 buf.append(omvIterator.iterate(oms, "Values:", false)); 1184 1185 oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); 1186 buf.append(omvIterator.iterate(oms, "Callee saved:", true)); 1187 1188 oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); 1189 buf.append(omvIterator.iterate(oms, "Derived oops:", true)); 1190 1191 buf.endTag("table"); 1192 return buf.toString(); 1193 } 1194 1195 1196 protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) { 1197 OopMapSet mapSet = nmethod.getOopMaps(); 1198 if (mapSet == null || (mapSet.getSize() <= 0)) 1199 return ""; 1200 int pcOffset = pcDesc.getPCOffset(); 1201 OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging()); 1202 if (map == null) { 1203 throw new IllegalArgumentException("no oopmap at safepoint!"); 1204 } 1205 1206 return genOopMapInfo(map); 1207 } 1208 1209 protected String genOopMapInfo(OopMap map) { 1210 Formatter buf = new Formatter(genHTML); 1211 buf.beginTag("pre"); 1212 buf.append("OopMap: "); 1213 buf.br(); 1214 buf.append(genHTMLForOopMap(map)); 1215 buf.endTag("pre"); 1216 1217 return buf.toString(); 1218 } 1219 1220 protected String locationAsString(Location loc) { 1221 Formatter buf = new Formatter(genHTML); 1222 if (loc.isIllegal()) { 1223 buf.append("illegal"); 1224 } else { 1225 Location.Where w = loc.getWhere(); 1226 Location.Type type = loc.getType(); 1227 1228 if (w == Location.Where.ON_STACK) { 1229 buf.append("stack[" + loc.getStackOffset() + "]"); 1230 } else if (w == Location.Where.IN_REGISTER) { 1231 boolean isFloat = (type == Location.Type.FLOAT_IN_DBL || 1232 type == Location.Type.DBL); 1233 int regNum = loc.getRegisterNumber(); 1234 VMReg vmReg = new VMReg(regNum); 1235 buf.append(VMRegImpl.getRegisterName(vmReg.getValue())); 1236 } 1237 1238 buf.append(", "); 1239 if (type == Location.Type.NORMAL) { 1240 buf.append("normal"); 1241 } else if (type == Location.Type.OOP) { 1242 buf.append("oop"); 1243 } else if (type == Location.Type.NARROWOOP) { 1244 buf.append("narrowoop"); 1245 } else if (type == Location.Type.INT_IN_LONG) { 1246 buf.append("int"); 1247 } else if (type == Location.Type.LNG) { 1248 buf.append("long"); 1249 } else if (type == Location.Type.FLOAT_IN_DBL) { 1250 buf.append("float"); 1251 } else if (type == Location.Type.DBL) { 1252 buf.append("double"); 1253 } else if (type == Location.Type.ADDR) { 1254 buf.append("address"); 1255 } else if (type == Location.Type.INVALID) { 1256 buf.append("invalid"); 1257 } 1258 } 1259 return buf.toString(); 1260 } 1261 1262 private String scopeValueAsString(ScopeDesc sd, ScopeValue sv) { 1263 Formatter buf = new Formatter(genHTML); 1264 if (sv.isConstantInt()) { 1265 buf.append("int "); 1266 ConstantIntValue intValue = (ConstantIntValue) sv; 1267 buf.append(Integer.toString(intValue.getValue())); 1268 } else if (sv.isConstantLong()) { 1269 buf.append("long "); 1270 ConstantLongValue longValue = (ConstantLongValue) sv; 1271 buf.append(Long.toString(longValue.getValue())); 1272 buf.append("L"); 1273 } else if (sv.isConstantDouble()) { 1274 buf.append("double "); 1275 ConstantDoubleValue dblValue = (ConstantDoubleValue) sv; 1276 buf.append(Double.toString(dblValue.getValue())); 1277 buf.append("D"); 1278 } else if (sv.isConstantOop()) { 1279 buf.append("oop "); 1280 ConstantOopReadValue oopValue = (ConstantOopReadValue) sv; 1281 OopHandle oopHandle = oopValue.getValue(); 1282 if (oopHandle != null) { 1283 buf.append(oopHandle.toString()); 1284 } else { 1285 buf.append("null"); 1286 } 1287 } else if (sv.isLocation()) { 1288 LocationValue lvalue = (LocationValue) sv; 1289 Location loc = lvalue.getLocation(); 1290 if (loc != null) { 1291 buf.append(locationAsString(loc)); 1292 } else { 1293 buf.append("null"); 1294 } 1295 } else if (sv.isObject()) { 1296 ObjectValue ov = (ObjectValue)sv; 1297 buf.append("#ScObj" + sd.getObjects().indexOf(ov)); 1298 } else { 1299 buf.append("unknown scope value " + sv); 1300 } 1301 return buf.toString(); 1302 } 1303 1304 protected String genHTMLForScopeValues(ScopeDesc sd, boolean locals, List values) { 1305 int length = values.size(); 1306 Formatter buf = new Formatter(genHTML); 1307 buf.append(locals? "locals " : "expressions "); 1308 for (int i = 0; i < length; i++) { 1309 ScopeValue sv = (ScopeValue) values.get(i); 1310 if (sv == null) { 1311 continue; 1312 } 1313 buf.append('('); 1314 if (locals) { 1315 Symbol name = sd.getMethod().getLocalVariableName(sd.getBCI(), i); 1316 if (name != null) { 1317 buf.append("'"); 1318 buf.append(name.asString()); 1319 buf.append('\''); 1320 } else { 1321 buf.append("["); 1322 buf.append(Integer.toString(i)); 1323 buf.append(']'); 1324 } 1325 } else { 1326 buf.append("["); 1327 buf.append(Integer.toString(i)); 1328 buf.append(']'); 1329 } 1330 1331 buf.append(", "); 1332 buf.append(scopeValueAsString(sd, sv)); 1333 buf.append(") "); 1334 } 1335 1336 return buf.toString(); 1337 } 1338 1339 protected String genHTMLForLocals(ScopeDesc sd, List locals) { 1340 return genHTMLForScopeValues(sd, true, locals); 1341 } 1342 1343 protected String genHTMLForExpressions(ScopeDesc sd, List expressions) { 1344 return genHTMLForScopeValues(sd, false, expressions); 1345 } 1346 1347 protected String genHTMLForMonitors(ScopeDesc sd, List monitors) { 1348 int length = monitors.size(); 1349 Formatter buf = new Formatter(genHTML); 1350 buf.append("monitors "); 1351 for (int i = 0; i < length; i++) { 1352 MonitorValue mv = (MonitorValue) monitors.get(i); 1353 if (mv == null) { 1354 continue; 1355 } 1356 buf.append("(owner = "); 1357 ScopeValue owner = mv.owner(); 1358 if (owner != null) { 1359 buf.append(scopeValueAsString(sd, owner)); 1360 } else { 1361 buf.append("null"); 1362 } 1363 buf.append(", lock = "); 1364 1365 Location loc = mv.basicLock(); 1366 if (loc != null) { 1367 buf.append(locationAsString(loc)); 1368 } else { 1369 buf.append("null"); 1370 } 1371 buf.append(") "); 1372 } 1373 return buf.toString(); 1374 } 1375 1376 public String genHTML(final NMethod nmethod) { 1377 try { 1378 final Formatter buf = new Formatter(genHTML); 1379 buf.genHTMLPrologue(genNMethodTitle(nmethod)); 1380 buf.h3("Method"); 1381 buf.append(genMethodAndKlassLink(nmethod.getMethod())); 1382 1383 buf.h3("Compiled Code"); 1384 sun.jvm.hotspot.debugger.Address codeBegin = nmethod.codeBegin(); 1385 sun.jvm.hotspot.debugger.Address codeEnd = nmethod.codeEnd(); 1386 final int codeSize = (int)codeEnd.minus(codeBegin); 1387 final long startPc = addressToLong(codeBegin); 1388 final byte[] code = new byte[codeSize]; 1389 for (int i=0; i < code.length; i++) 1390 code[i] = codeBegin.getJByteAt(i); 1391 1392 final long verifiedEntryPoint = addressToLong(nmethod.getVerifiedEntryPoint()); 1393 final long entryPoint = addressToLong(nmethod.getEntryPoint()); 1394 final Map safepoints = nmethod.getSafepoints(); 1395 1396 final SymbolFinder symFinder = createSymbolFinder(); 1397 final Disassembler disasm = createDisassembler(startPc, code); 1398 class NMethodVisitor implements InstructionVisitor { 1399 boolean prevWasCall; 1400 public void prologue() { 1401 prevWasCall = false; 1402 } 1403 1404 public void visit(long currentPc, Instruction instr) { 1405 String href = null; 1406 if (instr.isCall()) { 1407 CallInstruction call = (CallInstruction) instr; 1408 sun.jvm.hotspot.asm.Address addr = call.getBranchDestination(); 1409 href = genPCHref(currentPc, addr); 1410 } 1411 1412 if (currentPc == verifiedEntryPoint) { 1413 buf.bold("Verified Entry Point"); buf.br(); 1414 } 1415 if (currentPc == entryPoint) { 1416 buf.bold(">Entry Point"); buf.br(); 1417 } 1418 1419 PCDesc pcDesc = (PCDesc) safepoints.get(longToAddress(currentPc)); 1420 1421 boolean isSafepoint = (pcDesc != null); 1422 if (isSafepoint && prevWasCall) { 1423 buf.append(genSafepointInfo(nmethod, pcDesc)); 1424 } 1425 1426 buf.append("0x"); 1427 buf.append(Long.toHexString(currentPc)); 1428 buf.append(':'); 1429 buf.append(tab); 1430 1431 if (href != null) { 1432 buf.link(href, instr.asString(currentPc, symFinder)); 1433 } else { 1434 buf.append(instr.asString(currentPc, symFinder)); 1435 } 1436 1437 buf.br(); 1438 if (isSafepoint && !prevWasCall) { 1439 buf.append(genSafepointInfo(nmethod, pcDesc)); 1440 } 1441 1442 prevWasCall = instr.isCall(); 1443 } 1444 1445 public void epilogue() { 1446 } 1447 }; 1448 1449 disasm.decode(new NMethodVisitor()); 1450 1451 sun.jvm.hotspot.debugger.Address stubBegin = nmethod.stubBegin(); 1452 if (stubBegin != null) { 1453 sun.jvm.hotspot.debugger.Address stubEnd = nmethod.stubEnd(); 1454 buf.h3("Stub"); 1455 long stubStartPc = addressToLong(stubBegin); 1456 long stubEndPc = addressToLong(stubEnd); 1457 int range = (int) (stubEndPc - stubStartPc); 1458 byte[] stubCode = readBuffer(stubBegin, range); 1459 Disassembler disasm2 = createDisassembler(stubStartPc, stubCode); 1460 disasm2.decode(new NMethodVisitor()); 1461 } 1462 buf.genHTMLEpilogue(); 1463 return buf.toString(); 1464 } catch (Exception exp) { 1465 return genHTMLErrorMessage(exp); 1466 } 1467 } 1468 1469 public String genHTML(final CodeBlob blob) { 1470 try { 1471 final Formatter buf = new Formatter(genHTML); 1472 buf.genHTMLPrologue(genCodeBlobTitle(blob)); 1473 buf.h3("CodeBlob"); 1474 1475 buf.h3("Compiled Code"); 1476 final sun.jvm.hotspot.debugger.Address codeBegin = blob.instructionsBegin(); 1477 final int codeSize = blob.getInstructionsSize(); 1478 final long startPc = addressToLong(codeBegin); 1479 final byte[] code = new byte[codeSize]; 1480 for (int i=0; i < code.length; i++) 1481 code[i] = codeBegin.getJByteAt(i); 1482 1483 final SymbolFinder symFinder = createSymbolFinder(); 1484 final Disassembler disasm = createDisassembler(startPc, code); 1485 class CodeBlobVisitor implements InstructionVisitor { 1486 OopMapSet maps; 1487 OopMap curMap; 1488 int curMapIndex; 1489 long curMapOffset; 1490 public void prologue() { 1491 maps = blob.getOopMaps(); 1492 if (maps != null && (maps.getSize() > 0)) { 1493 curMap = maps.getMapAt(0); 1494 if (curMap != null) { 1495 curMapOffset = curMap.getOffset(); 1496 } 1497 } 1498 } 1499 1500 public void visit(long currentPc, Instruction instr) { 1501 String href = null; 1502 if (instr.isCall()) { 1503 CallInstruction call = (CallInstruction) instr; 1504 sun.jvm.hotspot.asm.Address addr = call.getBranchDestination(); 1505 href = genPCHref(currentPc, addr); 1506 } 1507 1508 buf.append("0x"); 1509 buf.append(Long.toHexString(currentPc)); 1510 buf.append(':'); 1511 buf.append(tab); 1512 1513 if (href != null) { 1514 buf.link(href, instr.asString(currentPc, symFinder)); 1515 } else { 1516 buf.append(instr.asString(currentPc, symFinder)); 1517 } 1518 buf.br(); 1519 1520 // See whether we have an oop map at this PC 1521 if (curMap != null) { 1522 long curOffset = currentPc - startPc; 1523 if (curOffset == curMapOffset) { 1524 buf.append(genOopMapInfo(curMap)); 1525 if (++curMapIndex >= maps.getSize()) { 1526 curMap = null; 1527 } else { 1528 curMap = maps.getMapAt(curMapIndex); 1529 if (curMap != null) { 1530 curMapOffset = curMap.getOffset(); 1531 } 1532 } 1533 } 1534 } 1535 } 1536 1537 public void epilogue() { 1538 } 1539 }; 1540 1541 disasm.decode(new CodeBlobVisitor()); 1542 1543 buf.genHTMLEpilogue(); 1544 return buf.toString(); 1545 } catch (Exception exp) { 1546 return genHTMLErrorMessage(exp); 1547 } 1548 } 1549 1550 protected String genInterpreterCodeletTitle(InterpreterCodelet codelet) { 1551 Formatter buf = new Formatter(genHTML); 1552 buf.append("Interpreter codelet ["); 1553 buf.append(codelet.codeBegin().toString()); 1554 buf.append(','); 1555 buf.append(codelet.codeEnd().toString()); 1556 buf.append(") - "); 1557 buf.append(codelet.getDescription()); 1558 return buf.toString(); 1559 } 1560 1561 protected String genInterpreterCodeletLinkPageHref(StubQueue stubq) { 1562 return genBaseHref() + "interp_codelets"; 1563 } 1564 1565 public String genInterpreterCodeletLinksPage() { 1566 Formatter buf = new Formatter(genHTML); 1567 buf.genHTMLPrologue("Interpreter Codelets"); 1568 buf.beginTag("ul"); 1569 1570 Interpreter interp = VM.getVM().getInterpreter(); 1571 StubQueue code = interp.getCode(); 1572 InterpreterCodelet stub = (InterpreterCodelet) code.getFirst(); 1573 while (stub != null) { 1574 buf.beginTag("li"); 1575 sun.jvm.hotspot.debugger.Address addr = stub.codeBegin(); 1576 buf.link(genPCHref(addressToLong(addr)), stub.getDescription() + " @" + addr); 1577 buf.endTag("li"); 1578 stub = (InterpreterCodelet) code.getNext(stub); 1579 } 1580 1581 buf.endTag("ul"); 1582 buf.genHTMLEpilogue(); 1583 return buf.toString(); 1584 } 1585 1586 public String genHTML(InterpreterCodelet codelet) { 1587 Formatter buf = new Formatter(genHTML); 1588 buf.genHTMLPrologue(genInterpreterCodeletTitle(codelet)); 1589 Interpreter interp = VM.getVM().getInterpreter(); 1590 StubQueue stubq = interp.getCode(); 1591 1592 if (genHTML) { 1593 buf.beginTag("h3"); 1594 buf.link(genInterpreterCodeletLinkPageHref(stubq), "View links for all codelets"); 1595 buf.endTag("h3"); 1596 buf.br(); 1597 } 1598 1599 Stub prev = stubq.getPrev(codelet); 1600 if (prev != null) { 1601 if (genHTML) { 1602 buf.beginTag("h3"); 1603 buf.link(genPCHref(addressToLong(prev.codeBegin())), "View Previous Codelet"); 1604 buf.endTag("h3"); 1605 buf.br(); 1606 } else { 1607 buf.h3("Previous Codelet = 0x" + Long.toHexString(addressToLong(prev.codeBegin()))); 1608 } 1609 } 1610 1611 buf.h3("Code"); 1612 long stubStartPc = addressToLong(codelet.codeBegin()); 1613 long stubEndPc = addressToLong(codelet.codeEnd()); 1614 int range = (int) (stubEndPc - stubStartPc); 1615 byte[] stubCode = readBuffer(codelet.codeBegin(), range); 1616 Disassembler disasm = createDisassembler(stubStartPc, stubCode); 1617 disasm.decode(new RawCodeVisitor(buf)); 1618 1619 1620 Stub next = stubq.getNext(codelet); 1621 if (next != null) { 1622 if (genHTML) { 1623 buf.beginTag("h3"); 1624 buf.link(genPCHref(addressToLong(next.codeBegin())), "View Next Codelet"); 1625 buf.endTag("h3"); 1626 } else { 1627 buf.h3("Next Codelet = 0x" + Long.toHexString(addressToLong(next.codeBegin()))); 1628 } 1629 } 1630 1631 buf.genHTMLEpilogue(); 1632 return buf.toString(); 1633 } 1634 1635 protected String genDumpKlassesTitle(InstanceKlass[] klasses) { 1636 return (klasses.length == 1) ? "Create .class for this class" 1637 : "Create .class for all classes"; 1638 } 1639 1640 protected String genDumpKlassesHref(InstanceKlass[] klasses) { 1641 StringBuffer buf = new StringBuffer(genBaseHref()); 1642 buf.append("jcore_multiple="); 1643 for (int k = 0; k < klasses.length; k++) { 1644 buf.append(klasses[k].getHandle().toString()); 1645 buf.append(','); 1646 } 1647 return buf.toString(); 1648 } 1649 1650 protected String genDumpKlassesLink(InstanceKlass[] klasses) { 1651 if (!genHTML) return ""; 1652 1653 Formatter buf = new Formatter(genHTML); 1654 buf.link(genDumpKlassesHref(klasses), genDumpKlassesTitle(klasses)); 1655 return buf.toString(); 1656 } 1657 1658 public String genHTMLForKlassNames(InstanceKlass[] klasses) { 1659 try { 1660 Formatter buf = new Formatter(genHTML); 1661 buf.genHTMLPrologue(); 1662 buf.h3(genDumpKlassesLink(klasses)); 1663 1664 buf.append(genHTMLListForKlassNames(klasses)); 1665 buf.genHTMLEpilogue(); 1666 return buf.toString(); 1667 } catch (Exception exp) { 1668 return genHTMLErrorMessage(exp); 1669 } 1670 } 1671 1672 protected String genHTMLListForKlassNames(InstanceKlass[] klasses) { 1673 final Formatter buf = new Formatter(genHTML); 1674 buf.beginTable(0); 1675 for (int i = 0; i < klasses.length; i++) { 1676 InstanceKlass ik = klasses[i]; 1677 buf.beginTag("tr"); 1678 buf.cell(genKlassLink(ik)); 1679 buf.endTag("tr"); 1680 } 1681 1682 buf.endTable(); 1683 return buf.toString(); 1684 } 1685 1686 public String genHTMLForMethodNames(InstanceKlass klass) { 1687 try { 1688 Formatter buf = new Formatter(genHTML); 1689 buf.genHTMLPrologue(); 1690 buf.append(genHTMLListForMethods(klass)); 1691 buf.genHTMLEpilogue(); 1692 return buf.toString(); 1693 } catch (Exception exp) { 1694 return genHTMLErrorMessage(exp); 1695 } 1696 } 1697 1698 protected String genHTMLListForMethods(InstanceKlass klass) { 1699 Formatter buf = new Formatter(genHTML); 1700 ObjArray methods = klass.getMethods(); 1701 int numMethods = (int) methods.getLength(); 1702 if (numMethods != 0) { 1703 buf.h3("Methods"); 1704 buf.beginTag("ul"); 1705 for (int m = 0; m < numMethods; m++) { 1706 Method mtd = (Method) methods.getObjAt(m); 1707 buf.li(genMethodLink(mtd) + ";"); 1708 } 1709 buf.endTag("ul"); 1710 } 1711 return buf.toString(); 1712 } 1713 1714 protected String genHTMLListForInterfaces(InstanceKlass klass) { 1715 try { 1716 Formatter buf = new Formatter(genHTML); 1717 ObjArray interfaces = klass.getLocalInterfaces(); 1718 int numInterfaces = (int) interfaces.getLength(); 1719 if (numInterfaces != 0) { 1720 buf.h3("Interfaces"); 1721 buf.beginTag("ul"); 1722 for (int i = 0; i < numInterfaces; i++) { 1723 InstanceKlass inf = (InstanceKlass) interfaces.getObjAt(i); 1724 buf.li(genKlassLink(inf)); 1725 } 1726 buf.endTag("ul"); 1727 } 1728 return buf.toString(); 1729 } catch (Exception exp) { 1730 return genHTMLErrorMessage(exp); 1731 } 1732 } 1733 1734 protected String genFieldModifierString(AccessFlags acc) { 1735 Formatter buf = new Formatter(genHTML); 1736 if (acc.isPrivate()) { 1737 buf.append("private "); 1738 } else if (acc.isProtected()) { 1739 buf.append("protected "); 1740 } else if (acc.isPublic()) { 1741 buf.append("public "); 1742 } 1743 1744 if (acc.isStatic()) { 1745 buf.append("static "); 1746 } 1747 1748 if (acc.isFinal()) { 1749 buf.append("final "); 1750 } 1751 if (acc.isVolatile()) { 1752 buf.append("volatile "); 1753 } 1754 if (acc.isTransient()) { 1755 buf.append("transient "); 1756 } 1757 1758 // javac generated flags 1759 if (acc.isSynthetic()) { 1760 buf.append("[synthetic] "); 1761 } 1762 return buf.toString(); 1763 } 1764 1765 public String genHTMLForFieldNames(InstanceKlass klass) { 1766 try { 1767 Formatter buf = new Formatter(genHTML); 1768 buf.genHTMLPrologue(); 1769 buf.append(genHTMLListForFields(klass)); 1770 buf.genHTMLEpilogue(); 1771 return buf.toString(); 1772 } catch (Exception exp) { 1773 return genHTMLErrorMessage(exp); 1774 } 1775 } 1776 1777 protected String genHTMLListForFields(InstanceKlass klass) { 1778 Formatter buf = new Formatter(genHTML); 1779 TypeArray fields = klass.getFields(); 1780 int numFields = (int) fields.getLength(); 1781 ConstantPool cp = klass.getConstants(); 1782 if (numFields != 0) { 1783 buf.h3("Fields"); 1784 buf.beginList(); 1785 for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) { 1786 int nameIndex = fields.getShortAt(f + InstanceKlass.NAME_INDEX_OFFSET); 1787 int sigIndex = fields.getShortAt(f + InstanceKlass.SIGNATURE_INDEX_OFFSET); 1788 int genSigIndex = fields.getShortAt(f + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET); 1789 Symbol f_name = cp.getSymbolAt(nameIndex); 1790 Symbol f_sig = cp.getSymbolAt(sigIndex); 1791 Symbol f_genSig = (genSigIndex != 0)? cp.getSymbolAt(genSigIndex) : null; 1792 AccessFlags acc = new AccessFlags(fields.getShortAt(f + InstanceKlass.ACCESS_FLAGS_OFFSET)); 1793 1794 buf.beginTag("li"); 1795 buf.append(genFieldModifierString(acc)); 1796 buf.append(' '); 1797 Formatter sigBuf = new Formatter(genHTML); 1798 new SignatureConverter(f_sig, sigBuf.getBuffer()).dispatchField(); 1799 buf.append(sigBuf.toString().replace('/', '.')); 1800 buf.append(' '); 1801 buf.append(f_name.asString()); 1802 buf.append(';'); 1803 // is it generic? 1804 if (f_genSig != null) { 1805 buf.append(" [signature "); 1806 buf.append(escapeHTMLSpecialChars(f_genSig.asString())); 1807 buf.append("] "); 1808 } 1809 buf.endTag("li"); 1810 } 1811 buf.endList(); 1812 } 1813 return buf.toString(); 1814 } 1815 1816 protected String genKlassHierarchyHref(InstanceKlass klass) { 1817 return genBaseHref() + "hierarchy=" + klass.getHandle(); 1818 } 1819 1820 protected String genKlassHierarchyTitle(InstanceKlass klass) { 1821 Formatter buf = new Formatter(genHTML); 1822 buf.append("Class Hierarchy of "); 1823 buf.append(genKlassTitle(klass)); 1824 return buf.toString(); 1825 } 1826 1827 protected String genKlassHierarchyLink(InstanceKlass klass) { 1828 Formatter buf = new Formatter(genHTML); 1829 buf.link(genKlassHierarchyHref(klass), genKlassHierarchyTitle(klass)); 1830 return buf.toString(); 1831 } 1832 1833 protected String genHTMLListForSubKlasses(InstanceKlass klass) { 1834 Formatter buf = new Formatter(genHTML); 1835 Klass subklass = klass.getSubklassKlass(); 1836 if (subklass != null) { 1837 buf.beginList(); 1838 while (subklass != null) { 1839 if (subklass instanceof InstanceKlass) { 1840 buf.li(genKlassLink((InstanceKlass)subklass)); 1841 } 1842 subklass = subklass.getNextSiblingKlass(); 1843 } 1844 buf.endList(); 1845 } 1846 return buf.toString(); 1847 } 1848 1849 public String genHTMLForKlassHierarchy(InstanceKlass klass) { 1850 Formatter buf = new Formatter(genHTML); 1851 buf.genHTMLPrologue(genKlassHierarchyTitle(klass)); 1852 1853 1854 buf.beginTag("pre"); 1855 buf.append(genKlassLink(klass)); 1856 buf.br(); 1857 StringBuffer tabs = new StringBuffer(tab); 1858 InstanceKlass superKlass = klass; 1859 while ( (superKlass = (InstanceKlass) superKlass.getSuper()) != null ) { 1860 buf.append(tabs); 1861 buf.append(genKlassLink(superKlass)); 1862 tabs.append(tab); 1863 buf.br(); 1864 } 1865 buf.endTag("pre"); 1866 1867 // generate subklass list 1868 Klass subklass = klass.getSubklassKlass(); 1869 if (subklass != null) { 1870 buf.h3("Direct Subclasses"); 1871 buf.append(genHTMLListForSubKlasses(klass)); 1872 } 1873 1874 buf.genHTMLEpilogue(); 1875 return buf.toString(); 1876 } 1877 1878 protected String genDumpKlassHref(InstanceKlass klass) { 1879 return genBaseHref() + "jcore=" + klass.getHandle(); 1880 } 1881 1882 protected String genDumpKlassLink(InstanceKlass klass) { 1883 if (!genHTML) return ""; 1884 1885 Formatter buf = new Formatter(genHTML); 1886 buf.link(genDumpKlassHref(klass), "Create .class File"); 1887 return buf.toString(); 1888 } 1889 1890 public String genHTML(InstanceKlass klass) { 1891 Formatter buf = new Formatter(genHTML); 1892 buf.genHTMLPrologue(genKlassTitle(klass)); 1893 InstanceKlass superKlass = (InstanceKlass) klass.getSuper(); 1894 1895 if (genHTML) { 1896 // super class tree and subclass list 1897 buf.beginTag("h3"); 1898 buf.link(genKlassHierarchyHref(klass), "View Class Hierarchy"); 1899 buf.endTag("h3"); 1900 } 1901 1902 // jcore - create .class link 1903 buf.h3(genDumpKlassLink(klass)); 1904 1905 // super class 1906 if (superKlass != null) { 1907 buf.h3("Super Class"); 1908 buf.append(genKlassLink(superKlass)); 1909 } 1910 1911 // interfaces 1912 buf.append(genHTMLListForInterfaces(klass)); 1913 1914 // fields 1915 buf.append(genHTMLListForFields(klass)); 1916 1917 // methods 1918 buf.append(genHTMLListForMethods(klass)); 1919 1920 // constant pool link 1921 buf.h3("Constant Pool"); 1922 buf.append(genConstantPoolLink(klass.getConstants())); 1923 1924 buf.genHTMLEpilogue(); 1925 return buf.toString(); 1926 } 1927 1928 protected sun.jvm.hotspot.debugger.Address parseAddress(String address) { 1929 VM vm = VM.getVM(); 1930 sun.jvm.hotspot.debugger.Address addr = vm.getDebugger().parseAddress(address); 1931 return addr; 1932 } 1933 1934 protected long addressToLong(sun.jvm.hotspot.debugger.Address addr) { 1935 return VM.getVM().getDebugger().getAddressValue(addr); 1936 } 1937 1938 protected sun.jvm.hotspot.debugger.Address longToAddress(long addr) { 1939 return parseAddress("0x" + Long.toHexString(addr)); 1940 } 1941 1942 protected Oop getOopAtAddress(sun.jvm.hotspot.debugger.Address addr) { 1943 OopHandle oopHandle = addr.addOffsetToAsOopHandle(0); 1944 return VM.getVM().getObjectHeap().newOop(oopHandle); 1945 } 1946 1947 protected Oop getOopAtAddress(String address) { 1948 sun.jvm.hotspot.debugger.Address addr = parseAddress(address); 1949 return getOopAtAddress(addr); 1950 } 1951 1952 private void dumpKlass(InstanceKlass kls) throws IOException { 1953 String klassName = kls.getName().asString(); 1954 klassName = klassName.replace('/', File.separatorChar); 1955 int index = klassName.lastIndexOf(File.separatorChar); 1956 File dir = null; 1957 if (index != -1) { 1958 String dirName = klassName.substring(0, index); 1959 dir = new File(DUMP_KLASS_OUTPUT_DIR, dirName); 1960 } else { 1961 dir = new File(DUMP_KLASS_OUTPUT_DIR); 1962 } 1963 1964 dir.mkdirs(); 1965 File f = new File(dir, klassName.substring(klassName.lastIndexOf(File.separatorChar) + 1) 1966 + ".class"); 1967 f.createNewFile(); 1968 FileOutputStream fis = new FileOutputStream(f); 1969 ClassWriter cw = new ClassWriter(kls, fis); 1970 cw.write(); 1971 } 1972 1973 public String genDumpKlass(InstanceKlass kls) { 1974 try { 1975 dumpKlass(kls); 1976 Formatter buf = new Formatter(genHTML); 1977 buf.genHTMLPrologue(genKlassTitle(kls)); 1978 buf.append(".class created for "); 1979 buf.append(genKlassLink(kls)); 1980 buf.genHTMLEpilogue(); 1981 return buf.toString(); 1982 } catch(IOException exp) { 1983 return genHTMLErrorMessage(exp); 1984 } 1985 } 1986 1987 protected String genJavaStackTraceTitle(JavaThread thread) { 1988 Formatter buf = new Formatter(genHTML); 1989 buf.append("Java Stack Trace for "); 1990 buf.append(thread.getThreadName()); 1991 return buf.toString(); 1992 } 1993 1994 public String genHTMLForJavaStackTrace(JavaThread thread) { 1995 Formatter buf = new Formatter(genHTML); 1996 buf.genHTMLPrologue(genJavaStackTraceTitle(thread)); 1997 1998 buf.append("Thread state = "); 1999 buf.append(thread.getThreadState().toString()); 2000 buf.br(); 2001 buf.beginTag("pre"); 2002 for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { 2003 Method method = vf.getMethod(); 2004 buf.append(" - "); 2005 buf.append(genMethodLink(method)); 2006 buf.append(" @bci = " + vf.getBCI()); 2007 2008 int lineNumber = method.getLineNumberFromBCI(vf.getBCI()); 2009 if (lineNumber != -1) { 2010 buf.append(", line = "); 2011 buf.append(lineNumber); 2012 } 2013 2014 sun.jvm.hotspot.debugger.Address pc = vf.getFrame().getPC(); 2015 if (pc != null) { 2016 buf.append(", pc = "); 2017 buf.link(genPCHref(addressToLong(pc)), pc.toString()); 2018 } 2019 2020 if (vf.isCompiledFrame()) { 2021 buf.append(" (Compiled"); 2022 } 2023 else if (vf.isInterpretedFrame()) { 2024 buf.append(" (Interpreted"); 2025 } 2026 2027 if (vf.mayBeImpreciseDbg()) { 2028 buf.append("; information may be imprecise"); 2029 } 2030 buf.append(")"); 2031 buf.br(); 2032 } 2033 2034 buf.endTag("pre"); 2035 buf.genHTMLEpilogue(); 2036 return buf.toString(); 2037 } 2038 2039 public String genHTMLForHyperlink(String href) { 2040 if (href.startsWith("klass=")) { 2041 href = href.substring(href.indexOf('=') + 1); 2042 Oop obj = getOopAtAddress(href); 2043 if (Assert.ASSERTS_ENABLED) { 2044 Assert.that(obj instanceof InstanceKlass, "class= href with improper InstanceKlass!"); 2045 } 2046 return genHTML((InstanceKlass) obj); 2047 } else if (href.startsWith("method=")) { 2048 href = href.substring(href.indexOf('=') + 1); 2049 Oop obj = getOopAtAddress(href); 2050 if (Assert.ASSERTS_ENABLED) { 2051 Assert.that(obj instanceof Method, "method= href with improper Method!"); 2052 } 2053 return genHTML((Method) obj); 2054 } else if (href.startsWith("nmethod=")) { 2055 String addr = href.substring(href.indexOf('=') + 1); 2056 Object obj = VMObjectFactory.newObject(NMethod.class, parseAddress(addr)); 2057 if (Assert.ASSERTS_ENABLED) { 2058 Assert.that(obj instanceof NMethod, "nmethod= href with improper NMethod!"); 2059 } 2060 return genHTML((NMethod) obj); 2061 } else if (href.startsWith("pc=")) { 2062 String address = href.substring(href.indexOf('=') + 1); 2063 return genHTML(parseAddress(address)); 2064 } else if (href.startsWith("pc_multiple=")) { 2065 int indexOfComma = href.indexOf(','); 2066 if (indexOfComma == -1) { 2067 String firstPC = href.substring(href.indexOf('=') + 1); 2068 return genHTMLForRawDisassembly(parseAddress(firstPC), null); 2069 } else { 2070 String firstPC = href.substring(href.indexOf('=') + 1, indexOfComma); 2071 return genHTMLForRawDisassembly(parseAddress(firstPC), href.substring(indexOfComma + 1)); 2072 } 2073 } else if (href.startsWith("interp_codelets")) { 2074 return genInterpreterCodeletLinksPage(); 2075 } else if (href.startsWith("hierarchy=")) { 2076 href = href.substring(href.indexOf('=') + 1); 2077 Oop obj = getOopAtAddress(href); 2078 if (Assert.ASSERTS_ENABLED) { 2079 Assert.that(obj instanceof InstanceKlass, "class= href with improper InstanceKlass!"); 2080 } 2081 return genHTMLForKlassHierarchy((InstanceKlass) obj); 2082 } else if (href.startsWith("cpool=")) { 2083 href = href.substring(href.indexOf('=') + 1); 2084 Oop obj = getOopAtAddress(href); 2085 if (Assert.ASSERTS_ENABLED) { 2086 Assert.that(obj instanceof ConstantPool, "cpool= href with improper ConstantPool!"); 2087 } 2088 return genHTML((ConstantPool) obj); 2089 } else if (href.startsWith("jcore=")) { 2090 href = href.substring(href.indexOf('=') + 1); 2091 Oop obj = getOopAtAddress(href); 2092 if (Assert.ASSERTS_ENABLED) { 2093 Assert.that(obj instanceof InstanceKlass, "jcore= href with improper InstanceKlass!"); 2094 } 2095 return genDumpKlass((InstanceKlass) obj); 2096 } else if (href.startsWith("jcore_multiple=")) { 2097 href = href.substring(href.indexOf('=') + 1); 2098 Formatter buf = new Formatter(genHTML); 2099 buf.genHTMLPrologue(); 2100 StringTokenizer st = new StringTokenizer(href, ","); 2101 while (st.hasMoreTokens()) { 2102 Oop obj = getOopAtAddress(st.nextToken()); 2103 if (Assert.ASSERTS_ENABLED) { 2104 Assert.that(obj instanceof InstanceKlass, "jcore_multiple= href with improper InstanceKlass!"); 2105 } 2106 2107 InstanceKlass kls = (InstanceKlass) obj; 2108 try { 2109 dumpKlass(kls); 2110 buf.append(".class created for "); 2111 buf.append(genKlassLink(kls)); 2112 } catch(Exception exp) { 2113 buf.bold("can't .class for " + 2114 genKlassTitle(kls) + 2115 " : " + 2116 exp.getMessage()); 2117 } 2118 buf.br(); 2119 } 2120 2121 buf.genHTMLEpilogue(); 2122 return buf.toString(); 2123 } else { 2124 if (Assert.ASSERTS_ENABLED) { 2125 Assert.that(false, "unknown href link!"); 2126 } 2127 return null; 2128 } 2129 } 2130 }