agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6879063 Sdiff agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser

agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java

Print this page




  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.ui.classbrowser;
  26 
  27 import java.io.*;
  28 import java.util.*;
  29 import sun.jvm.hotspot.asm.*;
  30 import sun.jvm.hotspot.asm.sparc.*;
  31 import sun.jvm.hotspot.asm.x86.*;
  32 import sun.jvm.hotspot.asm.ia64.*;
  33 import sun.jvm.hotspot.code.*;
  34 import sun.jvm.hotspot.compiler.*;
  35 import sun.jvm.hotspot.debugger.*;
  36 import sun.jvm.hotspot.interpreter.*;
  37 import sun.jvm.hotspot.memory.*;
  38 import sun.jvm.hotspot.oops.*;
  39 import sun.jvm.hotspot.runtime.*;
  40 import sun.jvm.hotspot.tools.jcore.*;
  41 import sun.jvm.hotspot.types.*;
  42 import sun.jvm.hotspot.utilities.*;
  43 
  44 public class HTMLGenerator implements /* imports */ ClassConstants {
  45     static class Formatter {
  46         boolean html;
  47         StringBuffer buf = new StringBuffer();
  48 
  49         Formatter(boolean h) {
  50             html = h;
  51         }
  52 


 164    private final String spaces;
 165    private final String tab;
 166 
 167    private boolean genHTML = true;
 168 
 169    public HTMLGenerator() {
 170        this(true);
 171    }
 172 
 173    public HTMLGenerator(boolean html) {
 174        genHTML = html;
 175        if (html) {
 176            spaces = "  ";
 177            tab = "    ";
 178        } else {
 179            spaces = "  ";
 180            tab = "    ";
 181        }
 182     }
 183 
 184    private static CPUHelper cpuHelper;
 185    static {
 186       VM.registerVMInitializedObserver(new Observer() {
 187          public void update(Observable o, Object data) {
 188             initialize();
 189          }
 190       });
 191    }
 192 
 193    private static synchronized void initialize() {
 194       String cpu = VM.getVM().getCPU();
 195       if (cpu.equals("sparc")) {
 196          cpuHelper = new SPARCHelper();
 197       } else if (cpu.equals("x86")) {
 198          cpuHelper = new X86Helper();
 199       } else if (cpu.equals("ia64")) {
 200          cpuHelper = new IA64Helper();
 201       } else {
 202           throw new RuntimeException("cpu '" + cpu + "' is not yet supported!");
 203       }
 204    }
 205 
 206    protected static synchronized CPUHelper getCPUHelper() {
 207       return cpuHelper;
 208    }
 209 
 210    protected String escapeHTMLSpecialChars(String value) {
 211       if (!genHTML) return value;
 212 
 213       Formatter buf = new Formatter(genHTML);
 214       int len = value.length();
 215       for (int i=0; i < len; i++) {
 216          char c = value.charAt(i);
 217          switch (c) {
 218             case '<':
 219                buf.append("&lt;");
 220                break;
 221             case '>':
 222                buf.append("&gt;");
 223                break;
 224             case '&':
 225                buf.append("&amp;");
 226                break;
 227             default:
 228                buf.append(c);
 229                break;


 758                   buf.cell(((Symbol)obj).asString().replace('/', '.'));
 759                } else {
 760                   buf.cell(genKlassLink((InstanceKlass)obj));
 761                }
 762                buf.endTag("tr");
 763             }
 764 
 765             buf.endTable();
 766          }
 767 
 768          // display constant pool hyperlink
 769          buf.h3("Constant Pool");
 770          buf.append(genConstantPoolLink(cpool));
 771          buf.genHTMLEpilogue();
 772          return buf.toString();
 773       } catch (Exception exp) {
 774          return genHTMLErrorMessage(exp);
 775       }
 776    }
 777 
 778    protected Disassembler createDisassembler(long startPc, byte[] code) {
 779       return getCPUHelper().createDisassembler(startPc, code);
 780    }
 781 
 782    protected SymbolFinder createSymbolFinder() {
 783       return new DummySymbolFinder();
 784    }
 785 
 786    // genHTML for a given address. Address may be a PC or
 787    // methodOop or klassOop.
 788 
 789    public String genHTMLForAddress(String addrStr) {
 790       return genHTML(parseAddress(addrStr));
 791    }
 792 
 793    public String genHTML(sun.jvm.hotspot.debugger.Address pc) {
 794       CodeBlob blob = null;
 795 
 796       try {
 797          blob = (CodeBlob)VM.getVM().getCodeCache().findBlobUnsafe(pc);
 798       } catch (Exception exp) {
 799          // ignore
 800       }
 801 


 819       // try methodOop, klassOop and constantPoolOop.
 820       try {
 821          Oop obj = getOopAtAddress(pc);
 822          if (obj != null) {
 823             if (obj instanceof Method) {
 824                return genHTML((Method) obj);
 825             } else if (obj instanceof InstanceKlass) {
 826                return genHTML((InstanceKlass) obj);
 827             } else if (obj instanceof ConstantPool) {
 828                return genHTML((ConstantPool) obj);
 829             }
 830          }
 831       } catch (Exception exp) {
 832          // ignore
 833       }
 834 
 835       // didn't find any. do raw disassembly.
 836       return genHTMLForRawDisassembly(pc, null);
 837    }
 838 
 839    protected byte[] readBuffer(sun.jvm.hotspot.debugger.Address addr, int size) {
 840       byte[] buf = new byte[size];
 841       for (int b = 0; b < size; b++) {
 842          buf[b] = (byte) addr.getJByteAt(b);
 843       }
 844       return buf;
 845    }
 846 
 847     public String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc, int size) {
 848       try {
 849          return genHTMLForRawDisassembly(startPc, null, readBuffer(startPc, size));
 850       } catch (Exception exp) {
 851          return genHTMLErrorMessage(exp);
 852       }
 853    }
 854 
 855    protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc,
 856                                              String prevPCs) {
 857       try {
 858          return genHTMLForRawDisassembly(startPc, prevPCs, readBuffer(startPc, NATIVE_CODE_SIZE));
 859       } catch (Exception exp) {
 860          return genHTMLErrorMessage(exp);
 861       }
 862    }
 863 
 864    protected String genPCHref(long targetPc) {
 865       return genBaseHref() + "pc=0x" + Long.toHexString(targetPc);
 866    }
 867 
 868    protected String genMultPCHref(String pcs) {
 869       StringBuffer buf = new StringBuffer(genBaseHref());
 870       buf.append("pc_multiple=");
 871       buf.append(pcs);
 872       return buf.toString();
 873    }
 874 
 875    protected String genPCHref(long currentPc, sun.jvm.hotspot.asm.Address addr) {
 876       String href = null;
 877       if (addr instanceof PCRelativeAddress) {
 878          PCRelativeAddress pcRelAddr = (PCRelativeAddress) addr;
 879          href = genPCHref(currentPc + pcRelAddr.getDisplacement());
 880       } else if(addr instanceof DirectAddress) {
 881          href =  genPCHref(((DirectAddress) addr).getValue());
 882       }
 883 
 884       return href;
 885    }
 886 
 887    class RawCodeVisitor implements InstructionVisitor {
 888       private int instrSize = 0;
 889       private Formatter buf;
 890       private SymbolFinder symFinder = createSymbolFinder();




 891 
 892       RawCodeVisitor(Formatter buf) {
 893          this.buf = buf;




 894       }



 895 
 896       public int getInstructionSize() {
 897          return  instrSize;
 898       }
 899 
 900       public void prologue() {
 901       }
 902 
 903       public void visit(long currentPc, Instruction instr) {
 904          String href = null;
 905           if (instr.isCall()) {
 906              CallInstruction call = (CallInstruction) instr;
 907              sun.jvm.hotspot.asm.Address addr = call.getBranchDestination();
 908              href = genPCHref(currentPc, addr);




 909           }
 910 
 911           instrSize += instr.getSize();
 912           buf.append("0x");
 913           buf.append(Long.toHexString(currentPc));
 914           buf.append(':');
 915           buf.append(tab);

 916 
 917           if (href != null) {
 918              buf.link(href, instr.asString(currentPc, symFinder));


 919           } else {
 920              buf.append(instr.asString(currentPc, symFinder));
 921           }













 922           buf.br();

 923       }

 924 





















 925       public void epilogue() {
 926       }
 927    };
 928 
 929    protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address addr,
 930                                              String prevPCs,
 931                                              byte[] code) {
 932       try {
 933          long startPc = addressToLong(addr);
 934          Disassembler disasm = createDisassembler(startPc, code);
 935          final Formatter buf = new Formatter(genHTML);
 936          buf.genHTMLPrologue("Disassembly @0x" + Long.toHexString(startPc));
 937 
 938          if (prevPCs != null && genHTML) {
 939              buf.beginTag("p");
 940              buf.link(genMultPCHref(prevPCs), "show previous code ..");
 941              buf.endTag("p");
 942          }
 943 
 944 
 945          buf.h3("Code");
 946          RawCodeVisitor visitor = new RawCodeVisitor(buf);
 947          disasm.decode(visitor);
 948 
 949          if (genHTML) buf.beginTag("p");
 950          Formatter tmpBuf = new Formatter(genHTML);

 951          tmpBuf.append("0x");
 952          tmpBuf.append(Long.toHexString(startPc + visitor.getInstructionSize()).toString());
 953          tmpBuf.append(",0x");
 954          tmpBuf.append(Long.toHexString(startPc));
 955          if (prevPCs != null) {
 956             tmpBuf.append(',');
 957             tmpBuf.append(prevPCs);
 958          }
 959          if (genHTML) {
 960              buf.link(genMultPCHref(tmpBuf.toString()), "show more code ..");
 961              buf.endTag("p");
 962          }
 963 
 964          buf.genHTMLEpilogue();
 965          return buf.toString();
 966       } catch (Exception exp) {
 967          return genHTMLErrorMessage(exp);
 968       }
 969    }
 970 
 971    protected String genSafepointInfo(NMethod nm, PCDesc pcDesc) {
 972       ScopeDesc sd = nm.getScopeDescAt(pcDesc.getRealPC(nm));
 973       Formatter buf = new Formatter(genHTML);
 974       Formatter tabs = new Formatter(genHTML);
 975 
 976       buf.beginTag("pre");
 977       genScope(buf, tabs, sd);
 978       buf.endTag("pre");
 979       buf.append(genOopMapInfo(nm, pcDesc));
 980 
 981       return buf.toString();
 982    }
 983 
 984     protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) {
 985         if (sd == null) {
 986             return;
 987         }
 988 
 989         genScope(buf, tabs, sd.sender());
 990 
 991         buf.append(tabs);
 992         Method m = sd.getMethod();
 993         buf.append(genMethodAndKlassLink(m));
 994         int bci = sd.getBCI();
 995         buf.append(" @ bci = ");
 996         buf.append(Integer.toString(bci));
 997 
 998         int line = m.getLineNumberFromBCI(bci);
 999         if (line != -1) {


1061                   tmpBuf.append(VMRegImpl.getRegisterName(vmContentReg.getValue()));
1062                }
1063                tmpBuf.append(spaces);
1064             }
1065             tmpBuf.endTag("td");
1066             tmpBuf.endTag("tr");
1067             return found ? tmpBuf : new Formatter(genHTML);
1068          }
1069       }
1070 
1071       buf.beginTable(0);
1072 
1073       OopMapValueIterator omvIterator = new OopMapValueIterator();
1074       OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE);
1075       buf.append(omvIterator.iterate(oms, "Oop:", false));
1076 
1077       oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
1078       buf.append(omvIterator.iterate(oms, "Value:", false));
1079 
1080       oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
1081       buf.append(omvIterator.iterate(oms, "Oop:", false));
1082 
1083       oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
1084       buf.append(omvIterator.iterate(oms, "Callee saved:",  true));
1085 
1086       oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE);
1087       buf.append(omvIterator.iterate(oms, "Derived oop:", true));
1088 
1089       buf.endTag("table");
1090       return buf.toString();
1091    }
1092 
1093 
1094    protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) {
1095       OopMapSet mapSet = nmethod.getOopMaps();
1096       int pcOffset = pcDesc.getPCOffset();
1097       OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
1098       if (map == null) {
1099          throw new IllegalArgumentException("no oopmap at safepoint!");
1100       }
1101 


1254 
1255          Location loc = mv.basicLock();
1256          if (loc != null) {
1257             buf.append(locationAsString(loc));
1258          } else {
1259             buf.append("null");
1260          }
1261          buf.append(") ");
1262       }
1263       return buf.toString();
1264    }
1265 
1266    public String genHTML(final NMethod nmethod) {
1267       try {
1268          final Formatter buf = new Formatter(genHTML);
1269          buf.genHTMLPrologue(genNMethodTitle(nmethod));
1270          buf.h3("Method");
1271          buf.append(genMethodAndKlassLink(nmethod.getMethod()));
1272 
1273          buf.h3("Compiled Code");
1274          sun.jvm.hotspot.debugger.Address codeBegin = nmethod.codeBegin();
1275          sun.jvm.hotspot.debugger.Address codeEnd   = nmethod.codeEnd();
1276          final int codeSize = (int)codeEnd.minus(codeBegin);
1277          final long startPc = addressToLong(codeBegin);
1278          final byte[] code = new byte[codeSize];
1279          for (int i=0; i < code.length; i++)
1280             code[i] = codeBegin.getJByteAt(i);
1281 
1282          final long verifiedEntryPoint = addressToLong(nmethod.getVerifiedEntryPoint());
1283          final long entryPoint = addressToLong(nmethod.getEntryPoint());
1284          final Map safepoints = nmethod.getSafepoints();
1285 
1286          final SymbolFinder symFinder = createSymbolFinder();
1287          final Disassembler disasm = createDisassembler(startPc, code);
1288          class NMethodVisitor implements InstructionVisitor {
1289             boolean prevWasCall;
1290             public void prologue() {
1291                prevWasCall = false;
1292             }
1293 
1294             public void visit(long currentPc, Instruction instr) {
1295                String href = null;
1296                if (instr.isCall()) {
1297                   CallInstruction call = (CallInstruction) instr;
1298                   sun.jvm.hotspot.asm.Address addr = call.getBranchDestination();
1299                   href = genPCHref(currentPc, addr);
1300                }
1301 
1302                if (currentPc == verifiedEntryPoint) {
1303                    buf.bold("Verified Entry Point"); buf.br();
1304                }
1305                if (currentPc == entryPoint) {
1306                    buf.bold(">Entry Point"); buf.br();
1307                }
1308 
1309                PCDesc pcDesc = (PCDesc) safepoints.get(longToAddress(currentPc));
1310 
1311                boolean isSafepoint = (pcDesc != null);
1312                if (isSafepoint && prevWasCall) {
1313                   buf.append(genSafepointInfo(nmethod, pcDesc));
1314                }
1315 
1316                buf.append("0x");
1317                buf.append(Long.toHexString(currentPc));
1318                buf.append(':');
1319                buf.append(tab);
1320 
1321                if (href != null) {
1322                   buf.link(href, instr.asString(currentPc, symFinder));
1323                } else {
1324                   buf.append(instr.asString(currentPc, symFinder));
1325                }
1326 
1327                if (isSafepoint && !prevWasCall) {
1328                   buf.append(genSafepointInfo(nmethod, pcDesc));
1329                }
1330 
1331                buf.br();
1332                prevWasCall = instr.isCall();
1333             }
1334 
1335             public void epilogue() {
1336             }
1337          };
1338 
1339          disasm.decode(new NMethodVisitor());
1340 
1341          sun.jvm.hotspot.debugger.Address stubBegin = nmethod.stubBegin();
1342          if (stubBegin != null) {
1343             sun.jvm.hotspot.debugger.Address stubEnd   = nmethod.stubEnd();
1344             buf.h3("Stub");
1345             long stubStartPc = addressToLong(stubBegin);
1346             long stubEndPc = addressToLong(stubEnd);
1347             int range = (int) (stubEndPc - stubStartPc);
1348             byte[] stubCode = readBuffer(stubBegin, range);
1349             Disassembler disasm2 = createDisassembler(stubStartPc, stubCode);
1350             disasm2.decode(new NMethodVisitor());
1351          }
1352          buf.genHTMLEpilogue();
1353          return buf.toString();
1354       } catch (Exception exp) {
1355          return genHTMLErrorMessage(exp);
1356       }
1357    }
1358 
1359   public String genHTML(final CodeBlob blob) {
1360       try {
1361          final Formatter buf = new Formatter(genHTML);
1362          buf.genHTMLPrologue(genCodeBlobTitle(blob));
1363          buf.h3("CodeBlob");
1364 
1365          buf.h3("Compiled Code");
1366          final sun.jvm.hotspot.debugger.Address codeBegin = blob.instructionsBegin();
1367          final int codeSize = blob.getInstructionsSize();
1368          final long startPc = addressToLong(codeBegin);
1369          final byte[] code = new byte[codeSize];
1370          for (int i=0; i < code.length; i++)
1371             code[i] = codeBegin.getJByteAt(i);
1372 
1373          final SymbolFinder symFinder = createSymbolFinder();
1374          final Disassembler disasm = createDisassembler(startPc, code);
1375          class CodeBlobVisitor implements InstructionVisitor {
1376             OopMapSet maps;
1377             OopMap curMap;
1378             int curMapIndex;
1379             long curMapOffset;
1380             public void prologue() {
1381               maps = blob.getOopMaps();
1382               if (maps != null && (maps.getSize() > 0)) {
1383                 curMap = maps.getMapAt(0);
1384                 if (curMap != null) {
1385                   curMapOffset = curMap.getOffset();
1386                 }
1387               }
1388             }
1389 
1390             public void visit(long currentPc, Instruction instr) {
1391                String href = null;
1392                if (instr.isCall()) {
1393                   CallInstruction call = (CallInstruction) instr;
1394                   sun.jvm.hotspot.asm.Address addr = call.getBranchDestination();
1395                   href = genPCHref(currentPc, addr);
1396                }
1397 
1398                buf.append("0x");
1399                buf.append(Long.toHexString(currentPc));
1400                buf.append(':');
1401                buf.append(tab);
1402 
1403                if (href != null) {
1404                   buf.link(href, instr.asString(currentPc, symFinder));
1405                } else {
1406                    buf.append(instr.asString(currentPc, symFinder));
1407                }
1408                buf.br();
1409 
1410                // See whether we have an oop map at this PC
1411                if (curMap != null) {
1412                  long curOffset = currentPc - startPc;
1413                  if (curOffset == curMapOffset) {
1414                    buf.append(genOopMapInfo(curMap));
1415                    if (++curMapIndex >= maps.getSize()) {
1416                      curMap = null;
1417                    } else {
1418                      curMap = maps.getMapAt(curMapIndex);
1419                      if (curMap != null) {
1420                        curMapOffset = curMap.getOffset();
1421                      }
1422                    }
1423                  }
1424                }
1425             }
1426 
1427             public void epilogue() {
1428             }
1429          };
1430 
1431          disasm.decode(new CodeBlobVisitor());
1432 
1433          buf.genHTMLEpilogue();
1434          return buf.toString();
1435       } catch (Exception exp) {
1436          return genHTMLErrorMessage(exp);
1437       }
1438    }
1439 
1440    protected String genInterpreterCodeletTitle(InterpreterCodelet codelet) {
1441       Formatter buf = new Formatter(genHTML);
1442       buf.append("Interpreter codelet [");
1443       buf.append(codelet.codeBegin().toString());
1444       buf.append(',');
1445       buf.append(codelet.codeEnd().toString());
1446       buf.append(") - ");
1447       buf.append(codelet.getDescription());
1448       return buf.toString();
1449    }
1450 
1451    protected String genInterpreterCodeletLinkPageHref(StubQueue stubq) {
1452       return genBaseHref() + "interp_codelets";


1482       if (genHTML) {
1483          buf.beginTag("h3");
1484          buf.link(genInterpreterCodeletLinkPageHref(stubq), "View links for all codelets");
1485          buf.endTag("h3");
1486          buf.br();
1487       }
1488 
1489       Stub prev = stubq.getPrev(codelet);
1490       if (prev != null) {
1491          if (genHTML) {
1492             buf.beginTag("h3");
1493             buf.link(genPCHref(addressToLong(prev.codeBegin())), "View Previous Codelet");
1494             buf.endTag("h3");
1495             buf.br();
1496          } else {
1497             buf.h3("Previous Codelet = 0x" + Long.toHexString(addressToLong(prev.codeBegin())));
1498          }
1499       }
1500 
1501       buf.h3("Code");
1502       long stubStartPc = addressToLong(codelet.codeBegin());
1503       long stubEndPc = addressToLong(codelet.codeEnd());
1504       int range = (int) (stubEndPc - stubStartPc);
1505       byte[] stubCode = readBuffer(codelet.codeBegin(), range);
1506       Disassembler disasm = createDisassembler(stubStartPc, stubCode);
1507       disasm.decode(new RawCodeVisitor(buf));
1508 
1509 
1510       Stub next = stubq.getNext(codelet);
1511       if (next != null) {
1512          if (genHTML) {
1513             buf.beginTag("h3");
1514             buf.link(genPCHref(addressToLong(next.codeBegin())), "View Next Codelet");
1515             buf.endTag("h3");
1516          } else {
1517             buf.h3("Next Codelet = 0x" + Long.toHexString(addressToLong(next.codeBegin())));
1518          }
1519       }
1520 
1521       buf.genHTMLEpilogue();
1522       return buf.toString();
1523    }
1524 
1525    protected String genDumpKlassesTitle(InstanceKlass[] klasses) {
1526       return (klasses.length == 1) ? "Create .class for this class"
1527                                    : "Create .class for all classes";
1528    }
1529 




  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.ui.classbrowser;
  26 
  27 import java.io.*;
  28 import java.util.*;
  29 import sun.jvm.hotspot.asm.*;



  30 import sun.jvm.hotspot.code.*;
  31 import sun.jvm.hotspot.compiler.*;
  32 import sun.jvm.hotspot.debugger.*;
  33 import sun.jvm.hotspot.interpreter.*;
  34 import sun.jvm.hotspot.memory.*;
  35 import sun.jvm.hotspot.oops.*;
  36 import sun.jvm.hotspot.runtime.*;
  37 import sun.jvm.hotspot.tools.jcore.*;
  38 import sun.jvm.hotspot.types.*;
  39 import sun.jvm.hotspot.utilities.*;
  40 
  41 public class HTMLGenerator implements /* imports */ ClassConstants {
  42     static class Formatter {
  43         boolean html;
  44         StringBuffer buf = new StringBuffer();
  45 
  46         Formatter(boolean h) {
  47             html = h;
  48         }
  49 


 161    private final String spaces;
 162    private final String tab;
 163 
 164    private boolean genHTML = true;
 165 
 166    public HTMLGenerator() {
 167        this(true);
 168    }
 169 
 170    public HTMLGenerator(boolean html) {
 171        genHTML = html;
 172        if (html) {
 173            spaces = "&nbsp;&nbsp;";
 174            tab = "&nbsp;&nbsp;&nbsp;&nbsp;";
 175        } else {
 176            spaces = "  ";
 177            tab = "    ";
 178        }
 179     }
 180 


























 181    protected String escapeHTMLSpecialChars(String value) {
 182       if (!genHTML) return value;
 183 
 184       Formatter buf = new Formatter(genHTML);
 185       int len = value.length();
 186       for (int i=0; i < len; i++) {
 187          char c = value.charAt(i);
 188          switch (c) {
 189             case '<':
 190                buf.append("&lt;");
 191                break;
 192             case '>':
 193                buf.append("&gt;");
 194                break;
 195             case '&':
 196                buf.append("&amp;");
 197                break;
 198             default:
 199                buf.append(c);
 200                break;


 729                   buf.cell(((Symbol)obj).asString().replace('/', '.'));
 730                } else {
 731                   buf.cell(genKlassLink((InstanceKlass)obj));
 732                }
 733                buf.endTag("tr");
 734             }
 735 
 736             buf.endTable();
 737          }
 738 
 739          // display constant pool hyperlink
 740          buf.h3("Constant Pool");
 741          buf.append(genConstantPoolLink(cpool));
 742          buf.genHTMLEpilogue();
 743          return buf.toString();
 744       } catch (Exception exp) {
 745          return genHTMLErrorMessage(exp);
 746       }
 747    }
 748 




 749    protected SymbolFinder createSymbolFinder() {
 750       return new DummySymbolFinder();
 751    }
 752 
 753    // genHTML for a given address. Address may be a PC or
 754    // methodOop or klassOop.
 755 
 756    public String genHTMLForAddress(String addrStr) {
 757       return genHTML(parseAddress(addrStr));
 758    }
 759 
 760    public String genHTML(sun.jvm.hotspot.debugger.Address pc) {
 761       CodeBlob blob = null;
 762 
 763       try {
 764          blob = (CodeBlob)VM.getVM().getCodeCache().findBlobUnsafe(pc);
 765       } catch (Exception exp) {
 766          // ignore
 767       }
 768 


 786       // try methodOop, klassOop and constantPoolOop.
 787       try {
 788          Oop obj = getOopAtAddress(pc);
 789          if (obj != null) {
 790             if (obj instanceof Method) {
 791                return genHTML((Method) obj);
 792             } else if (obj instanceof InstanceKlass) {
 793                return genHTML((InstanceKlass) obj);
 794             } else if (obj instanceof ConstantPool) {
 795                return genHTML((ConstantPool) obj);
 796             }
 797          }
 798       } catch (Exception exp) {
 799          // ignore
 800       }
 801 
 802       // didn't find any. do raw disassembly.
 803       return genHTMLForRawDisassembly(pc, null);
 804    }
 805 








 806     public String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc, int size) {
 807       try {
 808          return genHTMLForRawDisassembly(startPc, size, null);
 809       } catch (Exception exp) {
 810          return genHTMLErrorMessage(exp);
 811       }
 812    }
 813 
 814    protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc,
 815                                              String prevPCs) {
 816       try {
 817          return genHTMLForRawDisassembly(startPc, NATIVE_CODE_SIZE, prevPCs);
 818       } catch (Exception exp) {
 819          return genHTMLErrorMessage(exp);
 820       }
 821    }
 822 
 823    protected String genPCHref(long targetPc) {
 824       return genBaseHref() + "pc=0x" + Long.toHexString(targetPc);
 825    }
 826 
 827    protected String genMultPCHref(String pcs) {
 828       StringBuffer buf = new StringBuffer(genBaseHref());
 829       buf.append("pc_multiple=");
 830       buf.append(pcs);
 831       return buf.toString();
 832    }
 833 
 834    protected String genPCHref(Address addr) {
 835       return genPCHref(addressToLong(addr));





 836    }
 837 
 838    class HTMLDisassembler implements InstructionVisitor {



 839       private int instrSize = 0;
 840       private Formatter buf;
 841       private SymbolFinder symFinder = createSymbolFinder();
 842       private long pc;
 843       private OopMapSet oms;
 844       private CodeBlob blob;
 845       private NMethod nmethod;
 846 
 847       HTMLDisassembler(Formatter buf, CodeBlob blob) {
 848          this.buf = buf;
 849          this.blob = blob;
 850          if (blob != null) {
 851              if (blob instanceof NMethod) {
 852                  nmethod = (NMethod)blob;
 853              }
 854              oms = blob.getOopMaps();
 855          }
 856       }
 857 
 858       public int getInstructionSize() {
 859          return  instrSize;
 860       }
 861 
 862       public void prologue() {
 863       }
 864 
 865       public void beginInstruction(long currentPc) {
 866          pc = currentPc;
 867 
 868          Address adr = longToAddress(pc);
 869          if (nmethod != null) {
 870             if (adr.equals(nmethod.getEntryPoint()))             print("[Entry Point]\n");
 871             if (adr.equals(nmethod.getVerifiedEntryPoint()))     print("[Verified Entry Point]\n");
 872             if (adr.equals(nmethod.exceptionBegin()))            print("[Exception Handler]\n");
 873             if (adr.equals(nmethod.stubBegin()))                 print("[Stub Code]\n");
 874             // if (adr.equals(nmethod.constsBegin()))               print("[Constants]\n");
 875          }
 876 
 877          buf.append(adr.toString());


 878          buf.append(':');
 879          buf.append(tab);
 880       }
 881 
 882       public void printAddress(long address) {
 883          Address addr = longToAddress(address);
 884          if (VM.getVM().getCodeCache().contains(addr)) {
 885             buf.link(genPCHref(address), addr.toString());
 886          } else {
 887             buf.append(addr.toString());
 888          }
 889       }
 890 
 891       public void print(String s) {
 892          buf.append(s);
 893       }
 894 
 895       public void endInstruction(long endPc) {
 896          instrSize += endPc - pc;
 897          if (genHTML) buf.br();
 898 
 899          if (nmethod != null) {
 900             ScopeDesc sd = nmethod.scope_desc_in(pc, endPc);
 901             if (sd != null) {
 902                buf.br();
 903                buf.append(genSafepointInfo(nmethod, sd));
 904             }
 905          }
 906 
 907          if (oms != null) {
 908             long base = addressToLong(blob.instructionsBegin());
 909             for (int i = 0, imax = (int)oms.getSize(); i < imax; i++) {
 910                OopMap om = oms.getMapAt(i);
 911                long omspc = base + om.getOffset();
 912                if (omspc > pc) {
 913                   if (omspc <= endPc) {
 914                      buf.br();
 915                      buf.append(genOopMapInfo(om));
 916                      // st.move_to(column);
 917                      // visitor.print("; ");
 918                         // om.print_on(st);
 919                   }
 920                   break;
 921                }
 922             }
 923          }
 924          // follow each complete insn by a nice newline
 925          buf.br();
 926       }
 927 
 928       public void epilogue() {
 929       }
 930    };
 931 
 932    protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address addr,
 933                                              int size,
 934                                              String prevPCs) {
 935       try {


 936          final Formatter buf = new Formatter(genHTML);
 937          buf.genHTMLPrologue("Disassembly @ " + addr);
 938 
 939          if (prevPCs != null && genHTML) {
 940              buf.beginTag("p");
 941              buf.link(genMultPCHref(prevPCs), "show previous code ..");
 942              buf.endTag("p");
 943          }
 944 
 945 
 946          buf.h3("Code");
 947          HTMLDisassembler visitor = new HTMLDisassembler(buf, null);
 948          Disassembler.decode(visitor, null, addr, addr.addOffsetTo(size));
 949 
 950          if (genHTML) buf.beginTag("p");
 951          Formatter tmpBuf = new Formatter(genHTML);
 952          long startPc = addressToLong(addr);
 953          tmpBuf.append("0x");
 954          tmpBuf.append(Long.toHexString(startPc + visitor.getInstructionSize()).toString());
 955          tmpBuf.append(",0x");
 956          tmpBuf.append(Long.toHexString(startPc));
 957          if (prevPCs != null) {
 958             tmpBuf.append(',');
 959             tmpBuf.append(prevPCs);
 960          }
 961          if (genHTML) {
 962              buf.link(genMultPCHref(tmpBuf.toString()), "show more code ..");
 963              buf.endTag("p");
 964          }
 965 
 966          buf.genHTMLEpilogue();
 967          return buf.toString();
 968       } catch (Exception exp) {
 969          return genHTMLErrorMessage(exp);
 970       }
 971    }
 972 
 973    protected String genSafepointInfo(NMethod nm, ScopeDesc sd) {

 974       Formatter buf = new Formatter(genHTML);
 975       Formatter tabs = new Formatter(genHTML);
 976 
 977       buf.beginTag("pre");
 978       genScope(buf, tabs, sd);
 979       buf.endTag("pre");

 980 
 981       return buf.toString();
 982    }
 983 
 984     protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) {
 985         if (sd == null) {
 986             return;
 987         }
 988 
 989         genScope(buf, tabs, sd.sender());
 990 
 991         buf.append(tabs);
 992         Method m = sd.getMethod();
 993         buf.append(genMethodAndKlassLink(m));
 994         int bci = sd.getBCI();
 995         buf.append(" @ bci = ");
 996         buf.append(Integer.toString(bci));
 997 
 998         int line = m.getLineNumberFromBCI(bci);
 999         if (line != -1) {


1061                   tmpBuf.append(VMRegImpl.getRegisterName(vmContentReg.getValue()));
1062                }
1063                tmpBuf.append(spaces);
1064             }
1065             tmpBuf.endTag("td");
1066             tmpBuf.endTag("tr");
1067             return found ? tmpBuf : new Formatter(genHTML);
1068          }
1069       }
1070 
1071       buf.beginTable(0);
1072 
1073       OopMapValueIterator omvIterator = new OopMapValueIterator();
1074       OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE);
1075       buf.append(omvIterator.iterate(oms, "Oop:", false));
1076 
1077       oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
1078       buf.append(omvIterator.iterate(oms, "Value:", false));
1079 
1080       oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
1081       buf.append(omvIterator.iterate(oms, "NarrowOop:", false));
1082 
1083       oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
1084       buf.append(omvIterator.iterate(oms, "Callee saved:",  true));
1085 
1086       oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE);
1087       buf.append(omvIterator.iterate(oms, "Derived oop:", true));
1088 
1089       buf.endTag("table");
1090       return buf.toString();
1091    }
1092 
1093 
1094    protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) {
1095       OopMapSet mapSet = nmethod.getOopMaps();
1096       int pcOffset = pcDesc.getPCOffset();
1097       OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
1098       if (map == null) {
1099          throw new IllegalArgumentException("no oopmap at safepoint!");
1100       }
1101 


1254 
1255          Location loc = mv.basicLock();
1256          if (loc != null) {
1257             buf.append(locationAsString(loc));
1258          } else {
1259             buf.append("null");
1260          }
1261          buf.append(") ");
1262       }
1263       return buf.toString();
1264    }
1265 
1266    public String genHTML(final NMethod nmethod) {
1267       try {
1268          final Formatter buf = new Formatter(genHTML);
1269          buf.genHTMLPrologue(genNMethodTitle(nmethod));
1270          buf.h3("Method");
1271          buf.append(genMethodAndKlassLink(nmethod.getMethod()));
1272 
1273          buf.h3("Compiled Code");
1274          Disassembler.decode(new HTMLDisassembler(buf, nmethod), nmethod);













































































1275          buf.genHTMLEpilogue();
1276          return buf.toString();
1277       } catch (Exception exp) {
1278          return genHTMLErrorMessage(exp);
1279       }
1280    }
1281 
1282   public String genHTML(final CodeBlob blob) {
1283       try {
1284          final Formatter buf = new Formatter(genHTML);
1285          buf.genHTMLPrologue(genCodeBlobTitle(blob));
1286          buf.h3("CodeBlob");
1287 
1288          buf.h3("Compiled Code");
1289          Disassembler.decode(new HTMLDisassembler(buf, blob), blob);





1290 




























































1291          buf.genHTMLEpilogue();
1292          return buf.toString();
1293       } catch (Exception exp) {
1294          return genHTMLErrorMessage(exp);
1295       }
1296    }
1297 
1298    protected String genInterpreterCodeletTitle(InterpreterCodelet codelet) {
1299       Formatter buf = new Formatter(genHTML);
1300       buf.append("Interpreter codelet [");
1301       buf.append(codelet.codeBegin().toString());
1302       buf.append(',');
1303       buf.append(codelet.codeEnd().toString());
1304       buf.append(") - ");
1305       buf.append(codelet.getDescription());
1306       return buf.toString();
1307    }
1308 
1309    protected String genInterpreterCodeletLinkPageHref(StubQueue stubq) {
1310       return genBaseHref() + "interp_codelets";


1340       if (genHTML) {
1341          buf.beginTag("h3");
1342          buf.link(genInterpreterCodeletLinkPageHref(stubq), "View links for all codelets");
1343          buf.endTag("h3");
1344          buf.br();
1345       }
1346 
1347       Stub prev = stubq.getPrev(codelet);
1348       if (prev != null) {
1349          if (genHTML) {
1350             buf.beginTag("h3");
1351             buf.link(genPCHref(addressToLong(prev.codeBegin())), "View Previous Codelet");
1352             buf.endTag("h3");
1353             buf.br();
1354          } else {
1355             buf.h3("Previous Codelet = 0x" + Long.toHexString(addressToLong(prev.codeBegin())));
1356          }
1357       }
1358 
1359       buf.h3("Code");
1360       Disassembler.decode(new HTMLDisassembler(buf, null), null,
1361                           codelet.codeBegin(), codelet.codeEnd());




1362 

1363       Stub next = stubq.getNext(codelet);
1364       if (next != null) {
1365          if (genHTML) {
1366             buf.beginTag("h3");
1367             buf.link(genPCHref(addressToLong(next.codeBegin())), "View Next Codelet");
1368             buf.endTag("h3");
1369          } else {
1370             buf.h3("Next Codelet = 0x" + Long.toHexString(addressToLong(next.codeBegin())));
1371          }
1372       }
1373 
1374       buf.genHTMLEpilogue();
1375       return buf.toString();
1376    }
1377 
1378    protected String genDumpKlassesTitle(InstanceKlass[] klasses) {
1379       return (klasses.length == 1) ? "Create .class for this class"
1380                                    : "Create .class for all classes";
1381    }
1382 


agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File