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