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