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
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 = " ";
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
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
|