1 /* 2 * Copyright (c) 2002, 2011, 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") || cpu.equals("x86_64")) { 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 TypeArray exceptionTable = method.getExceptionTable(); 787 // exception table is 4 tuple array of shorts 788 int numEntries = (int)exceptionTable.getLength() / 4; 789 if (numEntries != 0) { 790 buf.h4("Exception Table"); 791 buf.beginTable(1); 792 buf.beginTag("tr"); 793 buf.headerCell("start bci"); 794 buf.headerCell("end bci"); 795 buf.headerCell("handler bci"); 796 buf.headerCell("catch type"); 797 buf.endTag("tr"); 798 799 for (int e = 0; e < numEntries; e += 4) { 800 buf.beginTag("tr"); 801 buf.cell(Integer.toString(exceptionTable.getIntAt(e))); 802 buf.cell(Integer.toString(exceptionTable.getIntAt(e + 1))); 803 buf.cell(Integer.toString(exceptionTable.getIntAt(e + 2))); 804 short cpIndex = (short) exceptionTable.getIntAt(e + 3); 805 ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex); 806 if (obj == null) { 807 buf.cell("Any"); 808 } else if (obj.isMetaData()) { 809 buf.cell(obj.getSymbol().asString().replace('/', '.')); 810 } else { 811 buf.cell(genKlassLink((InstanceKlass)obj.getOop())); 812 } 813 buf.endTag("tr"); 814 } 815 816 buf.endTable(); 817 } 818 819 // display constant pool hyperlink 820 buf.h3("Constant Pool"); 821 buf.append(genConstantPoolLink(cpool)); 822 buf.genHTMLEpilogue(); 823 return buf.toString(); 824 } catch (Exception exp) { 825 return genHTMLErrorMessage(exp); 826 } 827 } 828 829 protected Disassembler createDisassembler(long startPc, byte[] code) { 830 return getCPUHelper().createDisassembler(startPc, code); 831 } 832 833 protected SymbolFinder createSymbolFinder() { 834 return new DummySymbolFinder(); 835 } 836 837 // genHTML for a given address. Address may be a PC or 838 // methodOop or klassOop. 839 840 public String genHTMLForAddress(String addrStr) { 841 return genHTML(parseAddress(addrStr)); 842 } 843 844 public String genHTML(sun.jvm.hotspot.debugger.Address pc) { 845 CodeBlob blob = null; 846 847 try { 848 blob = (CodeBlob)VM.getVM().getCodeCache().findBlobUnsafe(pc); 849 } catch (Exception exp) { 850 // ignore 851 } 852 853 if (blob != null) { 854 if (blob instanceof NMethod) { 855 return genHTML((NMethod)blob); 856 } else { 857 // may be interpreter code. 858 Interpreter interp = VM.getVM().getInterpreter(); 859 if (interp.contains(pc)) { 860 InterpreterCodelet codelet = interp.getCodeletContaining(pc); 861 if (codelet == null) { 862 return "Unknown location in the Interpreter: " + pc; 863 } 864 return genHTML(codelet); 865 } 866 return genHTML(blob); 867 } 868 } else if (VM.getVM().getCodeCache().contains(pc)) { 869 return "Unknown location in the CodeCache: " + pc; 870 } 871 872 // did not find nmethod. 873 // try methodOop, klassOop and constantPoolOop. 874 try { 875 Oop obj = getOopAtAddress(pc); 876 if (obj != null) { 877 if (obj instanceof Method) { 878 return genHTML((Method) obj); 879 } else if (obj instanceof InstanceKlass) { 880 return genHTML((InstanceKlass) obj); 881 } else if (obj instanceof ConstantPool) { 882 return genHTML((ConstantPool) obj); 883 } 884 } 885 } catch (Exception exp) { 886 // ignore 887 } 888 889 // didn't find any. do raw disassembly. 890 return genHTMLForRawDisassembly(pc, null); 891 } 892 893 protected byte[] readBuffer(sun.jvm.hotspot.debugger.Address addr, int size) { 894 byte[] buf = new byte[size]; 895 for (int b = 0; b < size; b++) { 896 buf[b] = (byte) addr.getJByteAt(b); 897 } 898 return buf; 899 } 900 901 public String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc, int size) { 902 try { 903 return genHTMLForRawDisassembly(startPc, null, readBuffer(startPc, size)); 904 } catch (Exception exp) { 905 return genHTMLErrorMessage(exp); 906 } 907 } 908 909 protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc, 910 String prevPCs) { 911 try { 912 return genHTMLForRawDisassembly(startPc, prevPCs, readBuffer(startPc, NATIVE_CODE_SIZE)); 913 } catch (Exception exp) { 914 return genHTMLErrorMessage(exp); 915 } 916 } 917 918 protected String genPCHref(long targetPc) { 919 return genBaseHref() + "pc=0x" + Long.toHexString(targetPc); 920 } 921 922 protected String genMultPCHref(String pcs) { 923 StringBuffer buf = new StringBuffer(genBaseHref()); 924 buf.append("pc_multiple="); 925 buf.append(pcs); 926 return buf.toString(); 927 } 928 929 protected String genPCHref(long currentPc, sun.jvm.hotspot.asm.Address addr) { 930 String href = null; 931 if (addr instanceof PCRelativeAddress) { 932 PCRelativeAddress pcRelAddr = (PCRelativeAddress) addr; 933 href = genPCHref(currentPc + pcRelAddr.getDisplacement()); 934 } else if(addr instanceof DirectAddress) { 935 href = genPCHref(((DirectAddress) addr).getValue()); 936 } 937 938 return href; 939 } 940 941 class RawCodeVisitor implements InstructionVisitor { 942 private int instrSize = 0; 943 private Formatter buf; 944 private SymbolFinder symFinder = createSymbolFinder(); 945 946 RawCodeVisitor(Formatter buf) { 947 this.buf = buf; 948 } 949 950 public int getInstructionSize() { 951 return instrSize; 952 } 953 954 public void prologue() { 955 } 956 957 public void visit(long currentPc, Instruction instr) { 958 String href = null; 959 if (instr.isCall()) { 960 CallInstruction call = (CallInstruction) instr; 961 sun.jvm.hotspot.asm.Address addr = call.getBranchDestination(); 962 href = genPCHref(currentPc, addr); 963 } 964 965 instrSize += instr.getSize(); 966 buf.append("0x"); 967 buf.append(Long.toHexString(currentPc)); 968 buf.append(':'); 969 buf.append(tab); 970 971 if (href != null) { 972 buf.link(href, instr.asString(currentPc, symFinder)); 973 } else { 974 buf.append(instr.asString(currentPc, symFinder)); 975 } 976 buf.br(); 977 } 978 979 public void epilogue() { 980 } 981 }; 982 983 protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address addr, 984 String prevPCs, 985 byte[] code) { 986 try { 987 long startPc = addressToLong(addr); 988 Disassembler disasm = createDisassembler(startPc, code); 989 final Formatter buf = new Formatter(genHTML); 990 buf.genHTMLPrologue("Disassembly @0x" + Long.toHexString(startPc)); 991 992 if (prevPCs != null && genHTML) { 993 buf.beginTag("p"); 994 buf.link(genMultPCHref(prevPCs), "show previous code .."); 995 buf.endTag("p"); 996 } 997 998 999 buf.h3("Code"); 1000 RawCodeVisitor visitor = new RawCodeVisitor(buf); 1001 disasm.decode(visitor); 1002 1003 if (genHTML) buf.beginTag("p"); 1004 Formatter tmpBuf = new Formatter(genHTML); 1005 tmpBuf.append("0x"); 1006 tmpBuf.append(Long.toHexString(startPc + visitor.getInstructionSize()).toString()); 1007 tmpBuf.append(",0x"); 1008 tmpBuf.append(Long.toHexString(startPc)); 1009 if (prevPCs != null) { 1010 tmpBuf.append(','); 1011 tmpBuf.append(prevPCs); 1012 } 1013 if (genHTML) { 1014 buf.link(genMultPCHref(tmpBuf.toString()), "show more code .."); 1015 buf.endTag("p"); 1016 } 1017 1018 buf.genHTMLEpilogue(); 1019 return buf.toString(); 1020 } catch (Exception exp) { 1021 return genHTMLErrorMessage(exp); 1022 } 1023 } 1024 1025 protected String genSafepointInfo(NMethod nm, PCDesc pcDesc) { 1026 ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm)); 1027 Formatter buf = new Formatter(genHTML); 1028 Formatter tabs = new Formatter(genHTML); 1029 tabs.append(tab + tab + tab); // Initial indent for debug info 1030 1031 buf.beginTag("pre"); 1032 genScope(buf, tabs, sd); 1033 1034 // Reset indent for scalar replaced objects 1035 tabs = new Formatter(genHTML); 1036 tabs.append(tab + tab + tab); // Initial indent for debug info 1037 1038 genScObjInfo(buf, tabs, sd); 1039 buf.endTag("pre"); 1040 1041 buf.append(genOopMapInfo(nm, pcDesc)); 1042 1043 return buf.toString(); 1044 } 1045 1046 protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) { 1047 if (sd == null) { 1048 return; 1049 } 1050 1051 genScope(buf, tabs, sd.sender()); 1052 1053 buf.append(tabs); 1054 Method m = sd.getMethod(); 1055 buf.append(genMethodAndKlassLink(m)); 1056 int bci = sd.getBCI(); 1057 buf.append(" @ bci = "); 1058 buf.append(Integer.toString(bci)); 1059 1060 int line = m.getLineNumberFromBCI(bci); 1061 if (line != -1) { 1062 buf.append(", line = "); 1063 buf.append(Integer.toString(line)); 1064 } 1065 1066 List locals = sd.getLocals(); 1067 if (locals != null) { 1068 buf.br(); 1069 buf.append(tabs); 1070 buf.append(genHTMLForLocals(sd, locals)); 1071 } 1072 1073 List expressions = sd.getExpressions(); 1074 if (expressions != null) { 1075 buf.br(); 1076 buf.append(tabs); 1077 buf.append(genHTMLForExpressions(sd, expressions)); 1078 } 1079 1080 List monitors = sd.getMonitors(); 1081 if (monitors != null) { 1082 buf.br(); 1083 buf.append(tabs); 1084 buf.append(genHTMLForMonitors(sd, monitors)); 1085 } 1086 1087 buf.br(); 1088 tabs.append(tab); 1089 } 1090 1091 protected void genScObjInfo(Formatter buf, Formatter tabs, ScopeDesc sd) { 1092 if (sd == null) { 1093 return; 1094 } 1095 1096 List objects = sd.getObjects(); 1097 if (objects == null) { 1098 return; 1099 } 1100 int length = objects.size(); 1101 for (int i = 0; i < length; i++) { 1102 buf.append(tabs); 1103 ObjectValue ov = (ObjectValue)objects.get(i); 1104 buf.append("ScObj" + i); 1105 ScopeValue sv = ov.getKlass(); 1106 if (Assert.ASSERTS_ENABLED) { 1107 Assert.that(sv.isConstantOop(), "scalar replaced object klass must be constant oop"); 1108 } 1109 ConstantOopReadValue klv = (ConstantOopReadValue)sv; 1110 OopHandle klHandle = klv.getValue(); 1111 if (Assert.ASSERTS_ENABLED) { 1112 Assert.that(klHandle != null, "scalar replaced object klass must be not NULL"); 1113 } 1114 Oop obj = VM.getVM().getObjectHeap().newOop(klHandle); 1115 if (obj instanceof InstanceKlass) { 1116 InstanceKlass kls = (InstanceKlass) obj; 1117 buf.append(" " + kls.getName().asString() + "={"); 1118 int flen = ov.fieldsSize(); 1119 int klen = kls.getJavaFieldsCount(); 1120 int findex = 0; 1121 for (int index = 0; index < klen; index++) { 1122 int accsFlags = kls.getFieldAccessFlags(index); 1123 Symbol f_name = kls.getFieldName(index); 1124 AccessFlags access = new AccessFlags(accsFlags); 1125 if (!access.isStatic()) { 1126 ScopeValue svf = ov.getFieldAt(findex++); 1127 String fstr = scopeValueAsString(sd, svf); 1128 buf.append(" [" + f_name.asString() + " :"+ index + "]=(#" + fstr + ")"); 1129 } 1130 } 1131 buf.append(" }"); 1132 } else { 1133 buf.append(" "); 1134 int flen = ov.fieldsSize(); 1135 if (obj instanceof TypeArrayKlass) { 1136 TypeArrayKlass kls = (TypeArrayKlass) obj; 1137 buf.append(kls.getElementTypeName() + "[" + flen + "]"); 1138 } else if (obj instanceof ObjArrayKlass) { 1139 ObjArrayKlass kls = (ObjArrayKlass) obj; 1140 Klass elobj = kls.getBottomKlass(); 1141 if (elobj instanceof InstanceKlass) { 1142 buf.append(elobj.getName().asString()); 1143 } else if (elobj instanceof TypeArrayKlass) { 1144 TypeArrayKlass elkls = (TypeArrayKlass) elobj; 1145 buf.append(elkls.getElementTypeName()); 1146 } else { 1147 if (Assert.ASSERTS_ENABLED) { 1148 Assert.that(false, "unknown scalar replaced object klass!"); 1149 } 1150 } 1151 buf.append("[" + flen + "]"); 1152 int ndim = (int) kls.getDimension(); 1153 while (--ndim > 0) { 1154 buf.append("[]"); 1155 } 1156 } else { 1157 if (Assert.ASSERTS_ENABLED) { 1158 Assert.that(false, "unknown scalar replaced object klass!"); 1159 } 1160 } 1161 buf.append("={"); 1162 for (int findex = 0; findex < flen; findex++) { 1163 ScopeValue svf = ov.getFieldAt(findex); 1164 String fstr = scopeValueAsString(sd, svf); 1165 buf.append(" [" + findex + "]=(#" + fstr + ")"); 1166 } 1167 buf.append(" }"); 1168 } 1169 buf.br(); 1170 } 1171 } 1172 1173 protected String genHTMLForOopMap(OopMap map) { 1174 final int stack0 = VMRegImpl.getStack0().getValue(); 1175 Formatter buf = new Formatter(genHTML); 1176 1177 final class OopMapValueIterator { 1178 final Formatter iterate(OopMapStream oms, String type, boolean printContentReg) { 1179 Formatter tmpBuf = new Formatter(genHTML); 1180 boolean found = false; 1181 tmpBuf.beginTag("tr"); 1182 tmpBuf.beginTag("td"); 1183 tmpBuf.append(type); 1184 for (; ! oms.isDone(); oms.next()) { 1185 OopMapValue omv = oms.getCurrent(); 1186 if (omv == null) { 1187 continue; 1188 } 1189 found = true; 1190 VMReg vmReg = omv.getReg(); 1191 int reg = vmReg.getValue(); 1192 if (reg < stack0) { 1193 tmpBuf.append(VMRegImpl.getRegisterName(reg)); 1194 } else { 1195 tmpBuf.append('['); 1196 tmpBuf.append(Integer.toString((reg - stack0) * 4)); 1197 tmpBuf.append(']'); 1198 } 1199 if (printContentReg) { 1200 tmpBuf.append(" = "); 1201 VMReg vmContentReg = omv.getContentReg(); 1202 int contentReg = vmContentReg.getValue(); 1203 if (contentReg < stack0) { 1204 tmpBuf.append(VMRegImpl.getRegisterName(contentReg)); 1205 } else { 1206 tmpBuf.append('['); 1207 tmpBuf.append(Integer.toString((contentReg - stack0) * 4)); 1208 tmpBuf.append(']'); 1209 } 1210 } 1211 tmpBuf.append(spaces); 1212 } 1213 tmpBuf.endTag("td"); 1214 tmpBuf.endTag("tr"); 1215 return found ? tmpBuf : new Formatter(genHTML); 1216 } 1217 } 1218 1219 buf.beginTable(0); 1220 1221 OopMapValueIterator omvIterator = new OopMapValueIterator(); 1222 OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE); 1223 buf.append(omvIterator.iterate(oms, "Oops:", false)); 1224 1225 oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE); 1226 buf.append(omvIterator.iterate(oms, "narrowOops:", false)); 1227 1228 oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE); 1229 buf.append(omvIterator.iterate(oms, "Values:", false)); 1230 1231 oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); 1232 buf.append(omvIterator.iterate(oms, "Callee saved:", true)); 1233 1234 oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE); 1235 buf.append(omvIterator.iterate(oms, "Derived oops:", true)); 1236 1237 buf.endTag("table"); 1238 return buf.toString(); 1239 } 1240 1241 1242 protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) { 1243 OopMapSet mapSet = nmethod.getOopMaps(); 1244 if (mapSet == null || (mapSet.getSize() <= 0)) 1245 return ""; 1246 int pcOffset = pcDesc.getPCOffset(); 1247 OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging()); 1248 if (map == null) { 1249 throw new IllegalArgumentException("no oopmap at safepoint!"); 1250 } 1251 1252 return genOopMapInfo(map); 1253 } 1254 1255 protected String genOopMapInfo(OopMap map) { 1256 Formatter buf = new Formatter(genHTML); 1257 buf.beginTag("pre"); 1258 buf.append("OopMap: "); 1259 buf.br(); 1260 buf.append(genHTMLForOopMap(map)); 1261 buf.endTag("pre"); 1262 1263 return buf.toString(); 1264 } 1265 1266 protected String locationAsString(Location loc) { 1267 Formatter buf = new Formatter(genHTML); 1268 if (loc.isIllegal()) { 1269 buf.append("illegal"); 1270 } else { 1271 Location.Where w = loc.getWhere(); 1272 Location.Type type = loc.getType(); 1273 1274 if (w == Location.Where.ON_STACK) { 1275 buf.append("stack[" + loc.getStackOffset() + "]"); 1276 } else if (w == Location.Where.IN_REGISTER) { 1277 boolean isFloat = (type == Location.Type.FLOAT_IN_DBL || 1278 type == Location.Type.DBL); 1279 int regNum = loc.getRegisterNumber(); 1280 VMReg vmReg = new VMReg(regNum); 1281 buf.append(VMRegImpl.getRegisterName(vmReg.getValue())); 1282 } 1283 1284 buf.append(", "); 1285 if (type == Location.Type.NORMAL) { 1286 buf.append("normal"); 1287 } else if (type == Location.Type.OOP) { 1288 buf.append("oop"); 1289 } else if (type == Location.Type.NARROWOOP) { 1290 buf.append("narrowoop"); 1291 } else if (type == Location.Type.INT_IN_LONG) { 1292 buf.append("int"); 1293 } else if (type == Location.Type.LNG) { 1294 buf.append("long"); 1295 } else if (type == Location.Type.FLOAT_IN_DBL) { 1296 buf.append("float"); 1297 } else if (type == Location.Type.DBL) { 1298 buf.append("double"); 1299 } else if (type == Location.Type.ADDR) { 1300 buf.append("address"); 1301 } else if (type == Location.Type.INVALID) { 1302 buf.append("invalid"); 1303 } 1304 } 1305 return buf.toString(); 1306 } 1307 1308 private String scopeValueAsString(ScopeDesc sd, ScopeValue sv) { 1309 Formatter buf = new Formatter(genHTML); 1310 if (sv.isConstantInt()) { 1311 buf.append("int "); 1312 ConstantIntValue intValue = (ConstantIntValue) sv; 1313 buf.append(Integer.toString(intValue.getValue())); 1314 } else if (sv.isConstantLong()) { 1315 buf.append("long "); 1316 ConstantLongValue longValue = (ConstantLongValue) sv; 1317 buf.append(Long.toString(longValue.getValue())); 1318 buf.append("L"); 1319 } else if (sv.isConstantDouble()) { 1320 buf.append("double "); 1321 ConstantDoubleValue dblValue = (ConstantDoubleValue) sv; 1322 buf.append(Double.toString(dblValue.getValue())); 1323 buf.append("D"); 1324 } else if (sv.isConstantOop()) { 1325 buf.append("oop "); 1326 ConstantOopReadValue oopValue = (ConstantOopReadValue) sv; 1327 OopHandle oopHandle = oopValue.getValue(); 1328 if (oopHandle != null) { 1329 buf.append(oopHandle.toString()); 1330 } else { 1331 buf.append("null"); 1332 } 1333 } else if (sv.isLocation()) { 1334 LocationValue lvalue = (LocationValue) sv; 1335 Location loc = lvalue.getLocation(); 1336 if (loc != null) { 1337 buf.append(locationAsString(loc)); 1338 } else { 1339 buf.append("null"); 1340 } 1341 } else if (sv.isObject()) { 1342 ObjectValue ov = (ObjectValue)sv; 1343 buf.append("#ScObj" + sd.getObjects().indexOf(ov)); 1344 } else { 1345 buf.append("unknown scope value " + sv); 1346 } 1347 return buf.toString(); 1348 } 1349 1350 protected String genHTMLForScopeValues(ScopeDesc sd, boolean locals, List values) { 1351 int length = values.size(); 1352 Formatter buf = new Formatter(genHTML); 1353 buf.append(locals? "locals " : "expressions "); 1354 for (int i = 0; i < length; i++) { 1355 ScopeValue sv = (ScopeValue) values.get(i); 1356 if (sv == null) { 1357 continue; 1358 } 1359 buf.append('('); 1360 if (locals) { 1361 Symbol name = sd.getMethod().getLocalVariableName(sd.getBCI(), i); 1362 if (name != null) { 1363 buf.append("'"); 1364 buf.append(name.asString()); 1365 buf.append('\''); 1366 } else { 1367 buf.append("["); 1368 buf.append(Integer.toString(i)); 1369 buf.append(']'); 1370 } 1371 } else { 1372 buf.append("["); 1373 buf.append(Integer.toString(i)); 1374 buf.append(']'); 1375 } 1376 1377 buf.append(", "); 1378 buf.append(scopeValueAsString(sd, sv)); 1379 buf.append(") "); 1380 } 1381 1382 return buf.toString(); 1383 } 1384 1385 protected String genHTMLForLocals(ScopeDesc sd, List locals) { 1386 return genHTMLForScopeValues(sd, true, locals); 1387 } 1388 1389 protected String genHTMLForExpressions(ScopeDesc sd, List expressions) { 1390 return genHTMLForScopeValues(sd, false, expressions); 1391 } 1392 1393 protected String genHTMLForMonitors(ScopeDesc sd, List monitors) { 1394 int length = monitors.size(); 1395 Formatter buf = new Formatter(genHTML); 1396 buf.append("monitors "); 1397 for (int i = 0; i < length; i++) { 1398 MonitorValue mv = (MonitorValue) monitors.get(i); 1399 if (mv == null) { 1400 continue; 1401 } 1402 buf.append("(owner = "); 1403 ScopeValue owner = mv.owner(); 1404 if (owner != null) { 1405 buf.append(scopeValueAsString(sd, owner)); 1406 } else { 1407 buf.append("null"); 1408 } 1409 buf.append(", lock = "); 1410 1411 Location loc = mv.basicLock(); 1412 if (loc != null) { 1413 buf.append(locationAsString(loc)); 1414 } else { 1415 buf.append("null"); 1416 } 1417 buf.append(") "); 1418 } 1419 return buf.toString(); 1420 } 1421 1422 public String genHTML(final NMethod nmethod) { 1423 try { 1424 final Formatter buf = new Formatter(genHTML); 1425 buf.genHTMLPrologue(genNMethodTitle(nmethod)); 1426 buf.h3("Method"); 1427 buf.append(genMethodAndKlassLink(nmethod.getMethod())); 1428 1429 buf.h3("Compiled Code"); 1430 sun.jvm.hotspot.debugger.Address instsBegin = nmethod.instsBegin(); 1431 sun.jvm.hotspot.debugger.Address instsEnd = nmethod.instsEnd(); 1432 final int instsSize = nmethod.instsSize(); 1433 final long startPc = addressToLong(instsBegin); 1434 final byte[] code = new byte[instsSize]; 1435 for (int i=0; i < code.length; i++) 1436 code[i] = instsBegin.getJByteAt(i); 1437 1438 final long verifiedEntryPoint = addressToLong(nmethod.getVerifiedEntryPoint()); 1439 final long entryPoint = addressToLong(nmethod.getEntryPoint()); 1440 final Map safepoints = nmethod.getSafepoints(); 1441 1442 final SymbolFinder symFinder = createSymbolFinder(); 1443 final Disassembler disasm = createDisassembler(startPc, code); 1444 class NMethodVisitor implements InstructionVisitor { 1445 public void prologue() { 1446 } 1447 1448 public void visit(long currentPc, Instruction instr) { 1449 String href = null; 1450 if (instr.isCall()) { 1451 CallInstruction call = (CallInstruction) instr; 1452 sun.jvm.hotspot.asm.Address addr = call.getBranchDestination(); 1453 href = genPCHref(currentPc, addr); 1454 } 1455 1456 if (currentPc == verifiedEntryPoint) { 1457 buf.bold("Verified Entry Point"); buf.br(); 1458 } 1459 if (currentPc == entryPoint) { 1460 buf.bold(">Entry Point"); buf.br(); 1461 } 1462 1463 PCDesc pcDesc = (PCDesc) safepoints.get(longToAddress(currentPc)); 1464 1465 if (pcDesc != null) { 1466 buf.append(genSafepointInfo(nmethod, pcDesc)); 1467 } 1468 1469 buf.append("0x"); 1470 buf.append(Long.toHexString(currentPc)); 1471 buf.append(':'); 1472 buf.append(tab); 1473 1474 if (href != null) { 1475 buf.link(href, instr.asString(currentPc, symFinder)); 1476 } else { 1477 buf.append(instr.asString(currentPc, symFinder)); 1478 } 1479 1480 buf.br(); 1481 } 1482 1483 public void epilogue() { 1484 } 1485 }; 1486 1487 disasm.decode(new NMethodVisitor()); 1488 1489 sun.jvm.hotspot.debugger.Address stubBegin = nmethod.stubBegin(); 1490 if (stubBegin != null) { 1491 sun.jvm.hotspot.debugger.Address stubEnd = nmethod.stubEnd(); 1492 buf.h3("Stub"); 1493 long stubStartPc = addressToLong(stubBegin); 1494 long stubEndPc = addressToLong(stubEnd); 1495 int range = (int) (stubEndPc - stubStartPc); 1496 byte[] stubCode = readBuffer(stubBegin, range); 1497 Disassembler disasm2 = createDisassembler(stubStartPc, stubCode); 1498 disasm2.decode(new NMethodVisitor()); 1499 } 1500 buf.genHTMLEpilogue(); 1501 return buf.toString(); 1502 } catch (Exception exp) { 1503 return genHTMLErrorMessage(exp); 1504 } 1505 } 1506 1507 public String genHTML(final CodeBlob blob) { 1508 try { 1509 final Formatter buf = new Formatter(genHTML); 1510 buf.genHTMLPrologue(genCodeBlobTitle(blob)); 1511 buf.h3("CodeBlob"); 1512 1513 buf.h3("Compiled Code"); 1514 final sun.jvm.hotspot.debugger.Address codeBegin = blob.codeBegin(); 1515 final int codeSize = blob.getCodeSize(); 1516 final long startPc = addressToLong(codeBegin); 1517 final byte[] code = new byte[codeSize]; 1518 for (int i=0; i < code.length; i++) 1519 code[i] = codeBegin.getJByteAt(i); 1520 1521 final SymbolFinder symFinder = createSymbolFinder(); 1522 final Disassembler disasm = createDisassembler(startPc, code); 1523 class CodeBlobVisitor implements InstructionVisitor { 1524 OopMapSet maps; 1525 OopMap curMap; 1526 int curMapIndex; 1527 long curMapOffset; 1528 public void prologue() { 1529 maps = blob.getOopMaps(); 1530 if (maps != null && (maps.getSize() > 0)) { 1531 curMap = maps.getMapAt(0); 1532 if (curMap != null) { 1533 curMapOffset = curMap.getOffset(); 1534 } 1535 } 1536 } 1537 1538 public void visit(long currentPc, Instruction instr) { 1539 String href = null; 1540 if (instr.isCall()) { 1541 CallInstruction call = (CallInstruction) instr; 1542 sun.jvm.hotspot.asm.Address addr = call.getBranchDestination(); 1543 href = genPCHref(currentPc, addr); 1544 } 1545 1546 buf.append("0x"); 1547 buf.append(Long.toHexString(currentPc)); 1548 buf.append(':'); 1549 buf.append(tab); 1550 1551 if (href != null) { 1552 buf.link(href, instr.asString(currentPc, symFinder)); 1553 } else { 1554 buf.append(instr.asString(currentPc, symFinder)); 1555 } 1556 buf.br(); 1557 1558 // See whether we have an oop map at this PC 1559 if (curMap != null) { 1560 long curOffset = currentPc - startPc; 1561 if (curOffset == curMapOffset) { 1562 buf.append(genOopMapInfo(curMap)); 1563 if (++curMapIndex >= maps.getSize()) { 1564 curMap = null; 1565 } else { 1566 curMap = maps.getMapAt(curMapIndex); 1567 if (curMap != null) { 1568 curMapOffset = curMap.getOffset(); 1569 } 1570 } 1571 } 1572 } 1573 } 1574 1575 public void epilogue() { 1576 } 1577 }; 1578 1579 disasm.decode(new CodeBlobVisitor()); 1580 1581 buf.genHTMLEpilogue(); 1582 return buf.toString(); 1583 } catch (Exception exp) { 1584 return genHTMLErrorMessage(exp); 1585 } 1586 } 1587 1588 protected String genInterpreterCodeletTitle(InterpreterCodelet codelet) { 1589 Formatter buf = new Formatter(genHTML); 1590 buf.append("Interpreter codelet ["); 1591 buf.append(codelet.codeBegin().toString()); 1592 buf.append(','); 1593 buf.append(codelet.codeEnd().toString()); 1594 buf.append(") - "); 1595 buf.append(codelet.getDescription()); 1596 return buf.toString(); 1597 } 1598 1599 protected String genInterpreterCodeletLinkPageHref(StubQueue stubq) { 1600 return genBaseHref() + "interp_codelets"; 1601 } 1602 1603 public String genInterpreterCodeletLinksPage() { 1604 Formatter buf = new Formatter(genHTML); 1605 buf.genHTMLPrologue("Interpreter Codelets"); 1606 buf.beginTag("ul"); 1607 1608 Interpreter interp = VM.getVM().getInterpreter(); 1609 StubQueue code = interp.getCode(); 1610 InterpreterCodelet stub = (InterpreterCodelet) code.getFirst(); 1611 while (stub != null) { 1612 buf.beginTag("li"); 1613 sun.jvm.hotspot.debugger.Address addr = stub.codeBegin(); 1614 buf.link(genPCHref(addressToLong(addr)), stub.getDescription() + " @" + addr); 1615 buf.endTag("li"); 1616 stub = (InterpreterCodelet) code.getNext(stub); 1617 } 1618 1619 buf.endTag("ul"); 1620 buf.genHTMLEpilogue(); 1621 return buf.toString(); 1622 } 1623 1624 public String genHTML(InterpreterCodelet codelet) { 1625 Formatter buf = new Formatter(genHTML); 1626 buf.genHTMLPrologue(genInterpreterCodeletTitle(codelet)); 1627 Interpreter interp = VM.getVM().getInterpreter(); 1628 StubQueue stubq = interp.getCode(); 1629 1630 if (genHTML) { 1631 buf.beginTag("h3"); 1632 buf.link(genInterpreterCodeletLinkPageHref(stubq), "View links for all codelets"); 1633 buf.endTag("h3"); 1634 buf.br(); 1635 } 1636 1637 Stub prev = stubq.getPrev(codelet); 1638 if (prev != null) { 1639 if (genHTML) { 1640 buf.beginTag("h3"); 1641 buf.link(genPCHref(addressToLong(prev.codeBegin())), "View Previous Codelet"); 1642 buf.endTag("h3"); 1643 buf.br(); 1644 } else { 1645 buf.h3("Previous Codelet = 0x" + Long.toHexString(addressToLong(prev.codeBegin()))); 1646 } 1647 } 1648 1649 buf.h3("Code"); 1650 long stubStartPc = addressToLong(codelet.codeBegin()); 1651 long stubEndPc = addressToLong(codelet.codeEnd()); 1652 int range = (int) (stubEndPc - stubStartPc); 1653 byte[] stubCode = readBuffer(codelet.codeBegin(), range); 1654 Disassembler disasm = createDisassembler(stubStartPc, stubCode); 1655 disasm.decode(new RawCodeVisitor(buf)); 1656 1657 1658 Stub next = stubq.getNext(codelet); 1659 if (next != null) { 1660 if (genHTML) { 1661 buf.beginTag("h3"); 1662 buf.link(genPCHref(addressToLong(next.codeBegin())), "View Next Codelet"); 1663 buf.endTag("h3"); 1664 } else { 1665 buf.h3("Next Codelet = 0x" + Long.toHexString(addressToLong(next.codeBegin()))); 1666 } 1667 } 1668 1669 buf.genHTMLEpilogue(); 1670 return buf.toString(); 1671 } 1672 1673 protected String genDumpKlassesTitle(InstanceKlass[] klasses) { 1674 return (klasses.length == 1) ? "Create .class for this class" 1675 : "Create .class for all classes"; 1676 } 1677 1678 protected String genDumpKlassesHref(InstanceKlass[] klasses) { 1679 StringBuffer buf = new StringBuffer(genBaseHref()); 1680 buf.append("jcore_multiple="); 1681 for (int k = 0; k < klasses.length; k++) { 1682 buf.append(klasses[k].getHandle().toString()); 1683 buf.append(','); 1684 } 1685 return buf.toString(); 1686 } 1687 1688 protected String genDumpKlassesLink(InstanceKlass[] klasses) { 1689 if (!genHTML) return ""; 1690 1691 Formatter buf = new Formatter(genHTML); 1692 buf.link(genDumpKlassesHref(klasses), genDumpKlassesTitle(klasses)); 1693 return buf.toString(); 1694 } 1695 1696 public String genHTMLForKlassNames(InstanceKlass[] klasses) { 1697 try { 1698 Formatter buf = new Formatter(genHTML); 1699 buf.genHTMLPrologue(); 1700 buf.h3(genDumpKlassesLink(klasses)); 1701 1702 buf.append(genHTMLListForKlassNames(klasses)); 1703 buf.genHTMLEpilogue(); 1704 return buf.toString(); 1705 } catch (Exception exp) { 1706 return genHTMLErrorMessage(exp); 1707 } 1708 } 1709 1710 protected String genHTMLListForKlassNames(InstanceKlass[] klasses) { 1711 final Formatter buf = new Formatter(genHTML); 1712 buf.beginTable(0); 1713 for (int i = 0; i < klasses.length; i++) { 1714 InstanceKlass ik = klasses[i]; 1715 buf.beginTag("tr"); 1716 buf.cell(genKlassLink(ik)); 1717 buf.endTag("tr"); 1718 } 1719 1720 buf.endTable(); 1721 return buf.toString(); 1722 } 1723 1724 public String genHTMLForMethodNames(InstanceKlass klass) { 1725 try { 1726 Formatter buf = new Formatter(genHTML); 1727 buf.genHTMLPrologue(); 1728 buf.append(genHTMLListForMethods(klass)); 1729 buf.genHTMLEpilogue(); 1730 return buf.toString(); 1731 } catch (Exception exp) { 1732 return genHTMLErrorMessage(exp); 1733 } 1734 } 1735 1736 protected String genHTMLListForMethods(InstanceKlass klass) { 1737 Formatter buf = new Formatter(genHTML); 1738 ObjArray methods = klass.getMethods(); 1739 int numMethods = (int) methods.getLength(); 1740 if (numMethods != 0) { 1741 buf.h3("Methods"); 1742 buf.beginTag("ul"); 1743 for (int m = 0; m < numMethods; m++) { 1744 Method mtd = (Method) methods.getObjAt(m); 1745 buf.li(genMethodLink(mtd) + ";"); 1746 } 1747 buf.endTag("ul"); 1748 } 1749 return buf.toString(); 1750 } 1751 1752 protected String genHTMLListForInterfaces(InstanceKlass klass) { 1753 try { 1754 Formatter buf = new Formatter(genHTML); 1755 ObjArray interfaces = klass.getLocalInterfaces(); 1756 int numInterfaces = (int) interfaces.getLength(); 1757 if (numInterfaces != 0) { 1758 buf.h3("Interfaces"); 1759 buf.beginTag("ul"); 1760 for (int i = 0; i < numInterfaces; i++) { 1761 InstanceKlass inf = (InstanceKlass) interfaces.getObjAt(i); 1762 buf.li(genKlassLink(inf)); 1763 } 1764 buf.endTag("ul"); 1765 } 1766 return buf.toString(); 1767 } catch (Exception exp) { 1768 return genHTMLErrorMessage(exp); 1769 } 1770 } 1771 1772 protected String genFieldModifierString(AccessFlags acc) { 1773 Formatter buf = new Formatter(genHTML); 1774 if (acc.isPrivate()) { 1775 buf.append("private "); 1776 } else if (acc.isProtected()) { 1777 buf.append("protected "); 1778 } else if (acc.isPublic()) { 1779 buf.append("public "); 1780 } 1781 1782 if (acc.isStatic()) { 1783 buf.append("static "); 1784 } 1785 1786 if (acc.isFinal()) { 1787 buf.append("final "); 1788 } 1789 if (acc.isVolatile()) { 1790 buf.append("volatile "); 1791 } 1792 if (acc.isTransient()) { 1793 buf.append("transient "); 1794 } 1795 1796 // javac generated flags 1797 if (acc.isSynthetic()) { 1798 buf.append("[synthetic] "); 1799 } 1800 return buf.toString(); 1801 } 1802 1803 public String genHTMLForFieldNames(InstanceKlass klass) { 1804 try { 1805 Formatter buf = new Formatter(genHTML); 1806 buf.genHTMLPrologue(); 1807 buf.append(genHTMLListForFields(klass)); 1808 buf.genHTMLEpilogue(); 1809 return buf.toString(); 1810 } catch (Exception exp) { 1811 return genHTMLErrorMessage(exp); 1812 } 1813 } 1814 1815 protected String genHTMLListForFields(InstanceKlass klass) { 1816 Formatter buf = new Formatter(genHTML); 1817 int numFields = klass.getJavaFieldsCount(); 1818 if (numFields != 0) { 1819 buf.h3("Fields"); 1820 buf.beginList(); 1821 for (int f = 0; f < numFields; f++) { 1822 sun.jvm.hotspot.oops.Field field = klass.getFieldByIndex(f); 1823 String f_name = ((NamedFieldIdentifier)field.getID()).getName(); 1824 Symbol f_sig = field.getSignature(); 1825 Symbol f_genSig = field.getGenericSignature(); 1826 AccessFlags acc = field.getAccessFlagsObj(); 1827 1828 buf.beginListItem(); 1829 buf.append(genFieldModifierString(acc)); 1830 buf.append(' '); 1831 Formatter sigBuf = new Formatter(genHTML); 1832 new SignatureConverter(f_sig, sigBuf.getBuffer()).dispatchField(); 1833 buf.append(sigBuf.toString().replace('/', '.')); 1834 buf.append(' '); 1835 buf.append(f_name); 1836 buf.append(';'); 1837 // is it generic? 1838 if (f_genSig != null) { 1839 buf.append(" [signature "); 1840 buf.append(escapeHTMLSpecialChars(f_genSig.asString())); 1841 buf.append("] "); 1842 } 1843 buf.append(" (offset = " + field.getOffset() + ")"); 1844 buf.endListItem(); 1845 } 1846 buf.endList(); 1847 } 1848 return buf.toString(); 1849 } 1850 1851 protected String genKlassHierarchyHref(InstanceKlass klass) { 1852 return genBaseHref() + "hierarchy=" + klass.getHandle(); 1853 } 1854 1855 protected String genKlassHierarchyTitle(InstanceKlass klass) { 1856 Formatter buf = new Formatter(genHTML); 1857 buf.append("Class Hierarchy of "); 1858 buf.append(genKlassTitle(klass)); 1859 return buf.toString(); 1860 } 1861 1862 protected String genKlassHierarchyLink(InstanceKlass klass) { 1863 Formatter buf = new Formatter(genHTML); 1864 buf.link(genKlassHierarchyHref(klass), genKlassHierarchyTitle(klass)); 1865 return buf.toString(); 1866 } 1867 1868 protected String genHTMLListForSubKlasses(InstanceKlass klass) { 1869 Formatter buf = new Formatter(genHTML); 1870 Klass subklass = klass.getSubklassKlass(); 1871 if (subklass != null) { 1872 buf.beginList(); 1873 while (subklass != null) { 1874 if (subklass instanceof InstanceKlass) { 1875 buf.li(genKlassLink((InstanceKlass)subklass)); 1876 } 1877 subklass = subklass.getNextSiblingKlass(); 1878 } 1879 buf.endList(); 1880 } 1881 return buf.toString(); 1882 } 1883 1884 public String genHTMLForKlassHierarchy(InstanceKlass klass) { 1885 Formatter buf = new Formatter(genHTML); 1886 buf.genHTMLPrologue(genKlassHierarchyTitle(klass)); 1887 1888 1889 buf.beginTag("pre"); 1890 buf.append(genKlassLink(klass)); 1891 buf.br(); 1892 StringBuffer tabs = new StringBuffer(tab); 1893 InstanceKlass superKlass = klass; 1894 while ( (superKlass = (InstanceKlass) superKlass.getSuper()) != null ) { 1895 buf.append(tabs); 1896 buf.append(genKlassLink(superKlass)); 1897 tabs.append(tab); 1898 buf.br(); 1899 } 1900 buf.endTag("pre"); 1901 1902 // generate subklass list 1903 Klass subklass = klass.getSubklassKlass(); 1904 if (subklass != null) { 1905 buf.h3("Direct Subclasses"); 1906 buf.append(genHTMLListForSubKlasses(klass)); 1907 } 1908 1909 buf.genHTMLEpilogue(); 1910 return buf.toString(); 1911 } 1912 1913 protected String genDumpKlassHref(InstanceKlass klass) { 1914 return genBaseHref() + "jcore=" + klass.getHandle(); 1915 } 1916 1917 protected String genDumpKlassLink(InstanceKlass klass) { 1918 if (!genHTML) return ""; 1919 1920 Formatter buf = new Formatter(genHTML); 1921 buf.link(genDumpKlassHref(klass), "Create .class File"); 1922 return buf.toString(); 1923 } 1924 1925 public String genHTML(InstanceKlass klass) { 1926 Formatter buf = new Formatter(genHTML); 1927 buf.genHTMLPrologue(genKlassTitle(klass)); 1928 InstanceKlass superKlass = (InstanceKlass) klass.getSuper(); 1929 1930 if (genHTML) { 1931 // super class tree and subclass list 1932 buf.beginTag("h3"); 1933 buf.link(genKlassHierarchyHref(klass), "View Class Hierarchy"); 1934 buf.endTag("h3"); 1935 } 1936 1937 // jcore - create .class link 1938 buf.h3(genDumpKlassLink(klass)); 1939 1940 // super class 1941 if (superKlass != null) { 1942 buf.h3("Super Class"); 1943 buf.append(genKlassLink(superKlass)); 1944 } 1945 1946 // interfaces 1947 buf.append(genHTMLListForInterfaces(klass)); 1948 1949 // fields 1950 buf.append(genHTMLListForFields(klass)); 1951 1952 // methods 1953 buf.append(genHTMLListForMethods(klass)); 1954 1955 // constant pool link 1956 buf.h3("Constant Pool"); 1957 buf.append(genConstantPoolLink(klass.getConstants())); 1958 1959 buf.genHTMLEpilogue(); 1960 return buf.toString(); 1961 } 1962 1963 protected sun.jvm.hotspot.debugger.Address parseAddress(String address) { 1964 VM vm = VM.getVM(); 1965 sun.jvm.hotspot.debugger.Address addr = vm.getDebugger().parseAddress(address); 1966 return addr; 1967 } 1968 1969 protected long addressToLong(sun.jvm.hotspot.debugger.Address addr) { 1970 return VM.getVM().getDebugger().getAddressValue(addr); 1971 } 1972 1973 protected sun.jvm.hotspot.debugger.Address longToAddress(long addr) { 1974 return parseAddress("0x" + Long.toHexString(addr)); 1975 } 1976 1977 protected Oop getOopAtAddress(sun.jvm.hotspot.debugger.Address addr) { 1978 OopHandle oopHandle = addr.addOffsetToAsOopHandle(0); 1979 return VM.getVM().getObjectHeap().newOop(oopHandle); 1980 } 1981 1982 protected Oop getOopAtAddress(String address) { 1983 sun.jvm.hotspot.debugger.Address addr = parseAddress(address); 1984 return getOopAtAddress(addr); 1985 } 1986 1987 private void dumpKlass(InstanceKlass kls) throws IOException { 1988 String klassName = kls.getName().asString(); 1989 klassName = klassName.replace('/', File.separatorChar); 1990 int index = klassName.lastIndexOf(File.separatorChar); 1991 File dir = null; 1992 if (index != -1) { 1993 String dirName = klassName.substring(0, index); 1994 dir = new File(DUMP_KLASS_OUTPUT_DIR, dirName); 1995 } else { 1996 dir = new File(DUMP_KLASS_OUTPUT_DIR); 1997 } 1998 1999 dir.mkdirs(); 2000 File f = new File(dir, klassName.substring(klassName.lastIndexOf(File.separatorChar) + 1) 2001 + ".class"); 2002 f.createNewFile(); 2003 FileOutputStream fis = new FileOutputStream(f); 2004 ClassWriter cw = new ClassWriter(kls, fis); 2005 cw.write(); 2006 } 2007 2008 public String genDumpKlass(InstanceKlass kls) { 2009 try { 2010 dumpKlass(kls); 2011 Formatter buf = new Formatter(genHTML); 2012 buf.genHTMLPrologue(genKlassTitle(kls)); 2013 buf.append(".class created for "); 2014 buf.append(genKlassLink(kls)); 2015 buf.genHTMLEpilogue(); 2016 return buf.toString(); 2017 } catch(IOException exp) { 2018 return genHTMLErrorMessage(exp); 2019 } 2020 } 2021 2022 protected String genJavaStackTraceTitle(JavaThread thread) { 2023 Formatter buf = new Formatter(genHTML); 2024 buf.append("Java Stack Trace for "); 2025 buf.append(thread.getThreadName()); 2026 return buf.toString(); 2027 } 2028 2029 public String genHTMLForJavaStackTrace(JavaThread thread) { 2030 Formatter buf = new Formatter(genHTML); 2031 buf.genHTMLPrologue(genJavaStackTraceTitle(thread)); 2032 2033 buf.append("Thread state = "); 2034 buf.append(thread.getThreadState().toString()); 2035 buf.br(); 2036 buf.beginTag("pre"); 2037 for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { 2038 Method method = vf.getMethod(); 2039 buf.append(" - "); 2040 buf.append(genMethodLink(method)); 2041 buf.append(" @bci = " + vf.getBCI()); 2042 2043 int lineNumber = method.getLineNumberFromBCI(vf.getBCI()); 2044 if (lineNumber != -1) { 2045 buf.append(", line = "); 2046 buf.append(lineNumber); 2047 } 2048 2049 sun.jvm.hotspot.debugger.Address pc = vf.getFrame().getPC(); 2050 if (pc != null) { 2051 buf.append(", pc = "); 2052 buf.link(genPCHref(addressToLong(pc)), pc.toString()); 2053 } 2054 2055 if (vf.isCompiledFrame()) { 2056 buf.append(" (Compiled"); 2057 } 2058 else if (vf.isInterpretedFrame()) { 2059 buf.append(" (Interpreted"); 2060 } 2061 2062 if (vf.mayBeImpreciseDbg()) { 2063 buf.append("; information may be imprecise"); 2064 } 2065 buf.append(")"); 2066 buf.br(); 2067 } 2068 2069 buf.endTag("pre"); 2070 buf.genHTMLEpilogue(); 2071 return buf.toString(); 2072 } 2073 2074 public String genHTMLForHyperlink(String href) { 2075 if (href.startsWith("klass=")) { 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 genHTML((InstanceKlass) obj); 2082 } else if (href.startsWith("method=")) { 2083 href = href.substring(href.indexOf('=') + 1); 2084 Oop obj = getOopAtAddress(href); 2085 if (Assert.ASSERTS_ENABLED) { 2086 Assert.that(obj instanceof Method, "method= href with improper Method!"); 2087 } 2088 return genHTML((Method) obj); 2089 } else if (href.startsWith("nmethod=")) { 2090 String addr = href.substring(href.indexOf('=') + 1); 2091 Object obj = VMObjectFactory.newObject(NMethod.class, parseAddress(addr)); 2092 if (Assert.ASSERTS_ENABLED) { 2093 Assert.that(obj instanceof NMethod, "nmethod= href with improper NMethod!"); 2094 } 2095 return genHTML((NMethod) obj); 2096 } else if (href.startsWith("pc=")) { 2097 String address = href.substring(href.indexOf('=') + 1); 2098 return genHTML(parseAddress(address)); 2099 } else if (href.startsWith("pc_multiple=")) { 2100 int indexOfComma = href.indexOf(','); 2101 if (indexOfComma == -1) { 2102 String firstPC = href.substring(href.indexOf('=') + 1); 2103 return genHTMLForRawDisassembly(parseAddress(firstPC), null); 2104 } else { 2105 String firstPC = href.substring(href.indexOf('=') + 1, indexOfComma); 2106 return genHTMLForRawDisassembly(parseAddress(firstPC), href.substring(indexOfComma + 1)); 2107 } 2108 } else if (href.startsWith("interp_codelets")) { 2109 return genInterpreterCodeletLinksPage(); 2110 } else if (href.startsWith("hierarchy=")) { 2111 href = href.substring(href.indexOf('=') + 1); 2112 Oop obj = getOopAtAddress(href); 2113 if (Assert.ASSERTS_ENABLED) { 2114 Assert.that(obj instanceof InstanceKlass, "class= href with improper InstanceKlass!"); 2115 } 2116 return genHTMLForKlassHierarchy((InstanceKlass) obj); 2117 } else if (href.startsWith("cpool=")) { 2118 href = href.substring(href.indexOf('=') + 1); 2119 Oop obj = getOopAtAddress(href); 2120 if (Assert.ASSERTS_ENABLED) { 2121 Assert.that(obj instanceof ConstantPool, "cpool= href with improper ConstantPool!"); 2122 } 2123 return genHTML((ConstantPool) obj); 2124 } else if (href.startsWith("jcore=")) { 2125 href = href.substring(href.indexOf('=') + 1); 2126 Oop obj = getOopAtAddress(href); 2127 if (Assert.ASSERTS_ENABLED) { 2128 Assert.that(obj instanceof InstanceKlass, "jcore= href with improper InstanceKlass!"); 2129 } 2130 return genDumpKlass((InstanceKlass) obj); 2131 } else if (href.startsWith("jcore_multiple=")) { 2132 href = href.substring(href.indexOf('=') + 1); 2133 Formatter buf = new Formatter(genHTML); 2134 buf.genHTMLPrologue(); 2135 StringTokenizer st = new StringTokenizer(href, ","); 2136 while (st.hasMoreTokens()) { 2137 Oop obj = getOopAtAddress(st.nextToken()); 2138 if (Assert.ASSERTS_ENABLED) { 2139 Assert.that(obj instanceof InstanceKlass, "jcore_multiple= href with improper InstanceKlass!"); 2140 } 2141 2142 InstanceKlass kls = (InstanceKlass) obj; 2143 try { 2144 dumpKlass(kls); 2145 buf.append(".class created for "); 2146 buf.append(genKlassLink(kls)); 2147 } catch(Exception exp) { 2148 buf.bold("can't .class for " + 2149 genKlassTitle(kls) + 2150 " : " + 2151 exp.getMessage()); 2152 } 2153 buf.br(); 2154 } 2155 2156 buf.genHTMLEpilogue(); 2157 return buf.toString(); 2158 } else { 2159 if (Assert.ASSERTS_ENABLED) { 2160 Assert.that(false, "unknown href link!"); 2161 } 2162 return null; 2163 } 2164 } 2165 }