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("<");
220 break;
221 case '>':
222 buf.append(">");
223 break;
224 case '&':
225 buf.append("&");
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
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 = " ";
174 tab = " ";
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("<");
191 break;
192 case '>':
193 buf.append(">");
194 break;
195 case '&':
196 buf.append("&");
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
822 protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address startPc,
823 String prevPCs) {
824 try {
825 return genHTMLForRawDisassembly(startPc, prevPCs, readBuffer(startPc, NATIVE_CODE_SIZE));
826 } catch (Exception exp) {
827 return genHTMLErrorMessage(exp);
828 }
829 }
830
831 protected String genPCHref(long targetPc) {
832 return genBaseHref() + "pc=0x" + Long.toHexString(targetPc);
833 }
834
835 protected String genMultPCHref(String pcs) {
836 StringBuffer buf = new StringBuffer(genBaseHref());
837 buf.append("pc_multiple=");
838 buf.append(pcs);
839 return buf.toString();
840 }
841
842 protected String genPCHref(Address addr) {
843 return genPCHref(addressToLong(addr));
844 }
845
846 class HTMLDisassembler implements InstructionVisitor {
847 private int instrSize = 0;
848 private Formatter buf;
849 private SymbolFinder symFinder = createSymbolFinder();
850 private long pc;
851 private OopMapSet oms;
852 private CodeBlob blob;
853 private NMethod nmethod;
854
855 HTMLDisassembler(Formatter buf, CodeBlob blob) {
856 this.buf = buf;
857 this.blob = blob;
858 if (blob != null) {
859 if (blob instanceof NMethod) {
860 nmethod = (NMethod)blob;
861 }
862 oms = blob.getOopMaps();
863 }
864 }
865
866 public int getInstructionSize() {
867 return instrSize;
868 }
869
870 public void prologue() {
871 }
872
873 public void beginInstruction(long currentPc) {
874 pc = currentPc;
875
876 if (nmethod != null) {
877 if (pc == addressToLong(nmethod.getEntryPoint())) print("[Entry Point]\n");
878 if (pc == addressToLong(nmethod.getVerifiedEntryPoint())) print("[Verified Entry Point]\n");
879 if (pc == addressToLong(nmethod.exceptionBegin())) print("[Exception Handler]\n");
880 if (pc == addressToLong(nmethod.stubBegin())) print("[Stub Code]\n");
881 // if (p == addressToLong(nmethod.getConstsBegin())) print("[Constants]\n");
882 }
883
884 buf.append("0x");
885 buf.append(Long.toHexString(currentPc));
886 buf.append(':');
887 buf.append(tab);
888 }
889
890 public void printAddress(long address) {
891 Address addr = longToAddress(address);
892 if (VM.getVM().getCodeCache().contains(addr)) {
893 buf.link(genPCHref(address), addr.toString());
894 } else {
895 buf.append(addr.toString());
896 }
897 }
898
899 public void print(String s) {
900 buf.append(s);
901 }
902
903 public void endInstruction(long endPc) {
904 instrSize += endPc - pc;
905 if (genHTML) buf.br();
906
907 if (nmethod != null) {
908 ScopeDesc sd = nmethod.scope_desc_in(pc, endPc);
909 if (sd != null) {
910 buf.br();
911 buf.append(genSafepointInfo(nmethod, sd));
912 }
913 }
914
915 if (oms != null) {
916 long base = addressToLong(nmethod.instructionsBegin());
917 for (int i = 0, imax = (int)oms.getSize(); i < imax; i++) {
918 OopMap om = oms.getMapAt(i);
919 long omspc = base + om.getOffset();
920 if (omspc > pc) {
921 if (omspc <= endPc) {
922 buf.br();
923 buf.append(genOopMapInfo(om));
924 // st.move_to(column);
925 // visitor.print("; ");
926 // om.print_on(st);
927 }
928 break;
929 }
930 }
931 }
932 }
933
934 public void epilogue() {
935 }
936 };
937
938 protected String genHTMLForRawDisassembly(sun.jvm.hotspot.debugger.Address addr,
939 String prevPCs,
940 byte[] code) {
941 try {
942 final Formatter buf = new Formatter(genHTML);
943 buf.genHTMLPrologue("Disassembly @ " + addr);
944
945 if (prevPCs != null && genHTML) {
946 buf.beginTag("p");
947 buf.link(genMultPCHref(prevPCs), "show previous code ..");
948 buf.endTag("p");
949 }
950
951
952 buf.h3("Code");
953 HTMLDisassembler visitor = new HTMLDisassembler(buf, null);
954 Disassembler.decode(visitor, null, addr, addr.addOffsetTo(code.length));
955
956 if (genHTML) buf.beginTag("p");
957 Formatter tmpBuf = new Formatter(genHTML);
958 long startPc = addressToLong(addr);
959 tmpBuf.append("0x");
960 tmpBuf.append(Long.toHexString(startPc + visitor.getInstructionSize()).toString());
961 tmpBuf.append(",0x");
962 tmpBuf.append(Long.toHexString(startPc));
963 if (prevPCs != null) {
964 tmpBuf.append(',');
965 tmpBuf.append(prevPCs);
966 }
967 if (genHTML) {
968 buf.link(genMultPCHref(tmpBuf.toString()), "show more code ..");
969 buf.endTag("p");
970 }
971
972 buf.genHTMLEpilogue();
973 return buf.toString();
974 } catch (Exception exp) {
975 return genHTMLErrorMessage(exp);
976 }
977 }
978
979 protected String genSafepointInfo(NMethod nm, ScopeDesc sd) {
980 Formatter buf = new Formatter(genHTML);
981 Formatter tabs = new Formatter(genHTML);
982
983 buf.beginTag("pre");
984 genScope(buf, tabs, sd);
985 buf.endTag("pre");
986
987 return buf.toString();
988 }
989
990 protected void genScope(Formatter buf, Formatter tabs, ScopeDesc sd) {
991 if (sd == null) {
992 return;
993 }
994
995 genScope(buf, tabs, sd.sender());
996
997 buf.append(tabs);
998 Method m = sd.getMethod();
999 buf.append(genMethodAndKlassLink(m));
1000 int bci = sd.getBCI();
1001 buf.append(" @ bci = ");
1002 buf.append(Integer.toString(bci));
1003
1004 int line = m.getLineNumberFromBCI(bci);
1005 if (line != -1) {
1067 tmpBuf.append(VMRegImpl.getRegisterName(vmContentReg.getValue()));
1068 }
1069 tmpBuf.append(spaces);
1070 }
1071 tmpBuf.endTag("td");
1072 tmpBuf.endTag("tr");
1073 return found ? tmpBuf : new Formatter(genHTML);
1074 }
1075 }
1076
1077 buf.beginTable(0);
1078
1079 OopMapValueIterator omvIterator = new OopMapValueIterator();
1080 OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.OOP_VALUE);
1081 buf.append(omvIterator.iterate(oms, "Oop:", false));
1082
1083 oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
1084 buf.append(omvIterator.iterate(oms, "Value:", false));
1085
1086 oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
1087 buf.append(omvIterator.iterate(oms, "NarrowOop:", false));
1088
1089 oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
1090 buf.append(omvIterator.iterate(oms, "Callee saved:", true));
1091
1092 oms = new OopMapStream(map, OopMapValue.OopTypes.DERIVED_OOP_VALUE);
1093 buf.append(omvIterator.iterate(oms, "Derived oop:", true));
1094
1095 buf.endTag("table");
1096 return buf.toString();
1097 }
1098
1099
1100 protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) {
1101 OopMapSet mapSet = nmethod.getOopMaps();
1102 int pcOffset = pcDesc.getPCOffset();
1103 OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
1104 if (map == null) {
1105 throw new IllegalArgumentException("no oopmap at safepoint!");
1106 }
1107
1260
1261 Location loc = mv.basicLock();
1262 if (loc != null) {
1263 buf.append(locationAsString(loc));
1264 } else {
1265 buf.append("null");
1266 }
1267 buf.append(") ");
1268 }
1269 return buf.toString();
1270 }
1271
1272 public String genHTML(final NMethod nmethod) {
1273 try {
1274 final Formatter buf = new Formatter(genHTML);
1275 buf.genHTMLPrologue(genNMethodTitle(nmethod));
1276 buf.h3("Method");
1277 buf.append(genMethodAndKlassLink(nmethod.getMethod()));
1278
1279 buf.h3("Compiled Code");
1280 Disassembler.decode(new HTMLDisassembler(buf, nmethod), nmethod);
1281 buf.genHTMLEpilogue();
1282 return buf.toString();
1283 } catch (Exception exp) {
1284 return genHTMLErrorMessage(exp);
1285 }
1286 }
1287
1288 public String genHTML(final CodeBlob blob) {
1289 try {
1290 final Formatter buf = new Formatter(genHTML);
1291 buf.genHTMLPrologue(genCodeBlobTitle(blob));
1292 buf.h3("CodeBlob");
1293
1294 buf.h3("Compiled Code");
1295 Disassembler.decode(new HTMLDisassembler(buf, blob), blob);
1296
1297 buf.genHTMLEpilogue();
1298 return buf.toString();
1299 } catch (Exception exp) {
1300 return genHTMLErrorMessage(exp);
1301 }
1302 }
1303
1304 protected String genInterpreterCodeletTitle(InterpreterCodelet codelet) {
1305 Formatter buf = new Formatter(genHTML);
1306 buf.append("Interpreter codelet [");
1307 buf.append(codelet.codeBegin().toString());
1308 buf.append(',');
1309 buf.append(codelet.codeEnd().toString());
1310 buf.append(") - ");
1311 buf.append(codelet.getDescription());
1312 return buf.toString();
1313 }
1314
1315 protected String genInterpreterCodeletLinkPageHref(StubQueue stubq) {
1316 return genBaseHref() + "interp_codelets";
1346 if (genHTML) {
1347 buf.beginTag("h3");
1348 buf.link(genInterpreterCodeletLinkPageHref(stubq), "View links for all codelets");
1349 buf.endTag("h3");
1350 buf.br();
1351 }
1352
1353 Stub prev = stubq.getPrev(codelet);
1354 if (prev != null) {
1355 if (genHTML) {
1356 buf.beginTag("h3");
1357 buf.link(genPCHref(addressToLong(prev.codeBegin())), "View Previous Codelet");
1358 buf.endTag("h3");
1359 buf.br();
1360 } else {
1361 buf.h3("Previous Codelet = 0x" + Long.toHexString(addressToLong(prev.codeBegin())));
1362 }
1363 }
1364
1365 buf.h3("Code");
1366 Disassembler.decode(new HTMLDisassembler(buf, null), null,
1367 codelet.codeBegin(), codelet.codeEnd());
1368
1369 Stub next = stubq.getNext(codelet);
1370 if (next != null) {
1371 if (genHTML) {
1372 buf.beginTag("h3");
1373 buf.link(genPCHref(addressToLong(next.codeBegin())), "View Next Codelet");
1374 buf.endTag("h3");
1375 } else {
1376 buf.h3("Next Codelet = 0x" + Long.toHexString(addressToLong(next.codeBegin())));
1377 }
1378 }
1379
1380 buf.genHTMLEpilogue();
1381 return buf.toString();
1382 }
1383
1384 protected String genDumpKlassesTitle(InstanceKlass[] klasses) {
1385 return (klasses.length == 1) ? "Create .class for this class"
1386 : "Create .class for all classes";
1387 }
1388
|