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