Line data Source code
1 : /* src/vm/jit/show.cpp - showing the intermediate representation
2 :
3 : Copyright (C) 1996-2014
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 : #include "vm/jit/show.hpp"
26 : #include <assert.h> // for assert
27 : #include <stdint.h> // for int32_t
28 : #include <inttypes.h> // for printf formatting macros
29 : #include <stdio.h> // for printf, putchar, fflush
30 : #include "codegen-common.hpp" // for codegendata
31 : #include "config.h" // for ENABLE_DEBUG_FILTER, etc
32 : #include "patcher-common.hpp" // for patcher_list_show
33 : #include "replace.hpp"
34 : #include "threads/lock.hpp"
35 : #include "threads/mutex.hpp" // for Mutex
36 : #include "threads/thread.hpp" // for threadobject, etc
37 : #include "toolbox/buffer.hpp" // for Buffer
38 : #include "toolbox/list.hpp" // for LockedList
39 : #include "vm/class.hpp"
40 : #include "vm/descriptor.hpp" // for methoddesc, typedesc
41 : #include "vm/field.hpp" // for field_fieldref_print
42 : #include "vm/global.hpp" // for imm_union, Type::TYPE_RET, etc
43 : #include "vm/jit/abi.hpp" // for abi_registers_integer_name
44 : #include "vm/jit/builtin.hpp" // for builtintable_entry
45 : #include "vm/jit/code.hpp" // for codeinfo, etc
46 : #include "vm/jit/disass.hpp"
47 : #include "vm/jit/ir/icmd.hpp" // for ::ICMD_GETSTATIC, etc
48 : #include "vm/jit/ir/instruction.hpp" // for instruction, etc
49 : #include "vm/jit/jit.hpp" // for basicblock, jitdata, etc
50 : #include "vm/jit/linenumbertable.hpp" // for LinenumberTable
51 : #include "vm/jit/parse.hpp"
52 : #include "vm/jit/patcher-common.hpp"
53 : #include "vm/jit/reg.hpp" // for varinfo, etc
54 : #include "vm/jit/stack.hpp"
55 : #include "vm/method.hpp" // for methodinfo, etc
56 : #include "vm/options.hpp" // for opt_filter_show_method, etc
57 : #include "vm/references.hpp" // for classref_or_classinfo, etc
58 : #include "vm/string.hpp" // for JavaString
59 : #include "vm/types.hpp" // for s4, ptrint, u1, u2
60 : #include "vm/utf8.hpp" // for utf_display_printable_ascii
61 : #include "vm/vm.hpp" // for vm_abort
62 :
63 :
64 : #if defined(ENABLE_DEBUG_FILTER)
65 : # include <sys/types.h>
66 : # include <regex.h> // for regcomp, regerror, regexec, etc
67 : # include "threads/thread.hpp"
68 : #endif
69 :
70 : /* global variables ***********************************************************/
71 :
72 : #if !defined(NDEBUG)
73 165 : static Mutex mutex;
74 : #endif
75 :
76 :
77 : /* prototypes *****************************************************************/
78 :
79 : #if !defined(NDEBUG)
80 : static void show_variable_intern(jitdata *jd, s4 index, int stage);
81 : #endif
82 :
83 :
84 : /* show_init *******************************************************************
85 :
86 : Initialized the show subsystem (called by jit_init).
87 :
88 : *******************************************************************************/
89 :
90 : #if !defined(NDEBUG)
91 163 : bool show_init(void)
92 : {
93 : #if defined(ENABLE_DEBUG_FILTER)
94 163 : show_filters_init();
95 : #endif
96 :
97 : /* everything's ok */
98 :
99 163 : return true;
100 : }
101 : #endif
102 :
103 :
104 : #if !defined(NDEBUG)
105 : const char *show_jit_type_names[] = {
106 : "INT",
107 : "LNG",
108 : "FLT",
109 : "DBL",
110 : "ADR",
111 : "??5",
112 : "??6",
113 : "??7",
114 : "RET"
115 : };
116 :
117 : const char show_jit_type_letters[] = {
118 : 'I',
119 : 'L',
120 : 'F',
121 : 'D',
122 : 'A',
123 : '5',
124 : '6',
125 : '7',
126 : 'R'
127 : };
128 : #endif
129 :
130 :
131 : /* show_method *****************************************************************
132 :
133 : Print the intermediate representation of a method.
134 :
135 : NOTE: Currently this function may only be called after register allocation!
136 :
137 : *******************************************************************************/
138 :
139 : #if !defined(NDEBUG)
140 0 : void show_method(jitdata *jd, int stage)
141 : {
142 : methodinfo *m;
143 : codeinfo *code;
144 : codegendata *cd;
145 : registerdata *rd;
146 : basicblock *bptr;
147 : basicblock *lastbptr;
148 : exception_entry *ex;
149 : s4 i, j;
150 : int irstage;
151 : #if defined(ENABLE_DISASSEMBLER)
152 : u1 *pc;
153 : #endif
154 :
155 : /* get required compiler data */
156 :
157 0 : m = jd->m;
158 0 : code = jd->code;
159 0 : cd = jd->cd;
160 0 : rd = jd->rd;
161 :
162 : // We need to enter a lock here, since the binutils disassembler
163 : // is not reentrant-able and we could not read functions printed
164 : // at the same time.
165 0 : mutex.lock();
166 :
167 : #if defined(ENABLE_INTRP)
168 : if (opt_intrp)
169 : irstage = SHOW_PARSE;
170 : else
171 : #endif
172 0 : irstage = stage;
173 :
174 : /* get the last basic block */
175 :
176 0 : for (lastbptr = jd->basicblocks; lastbptr->next != NULL; lastbptr = lastbptr->next);
177 :
178 0 : printf("\n");
179 :
180 0 : method_println(m);
181 :
182 0 : if (code_is_leafmethod(code))
183 0 : printf("LEAFMETHOD\n");
184 :
185 0 : printf("\nBasic blocks: %d\n", jd->basicblockcount);
186 0 : if (stage >= SHOW_CODE) {
187 0 : printf("Code length: %d\n", (lastbptr->mpc - jd->basicblocks[0].mpc));
188 0 : printf("Data length: %d\n", cd->dseglen);
189 : printf("Stub length: %d\n", (s4) (code->mcodelength -
190 0 : ((ptrint) cd->dseglen + lastbptr->mpc)));
191 : }
192 0 : printf("Variables: %d (%d used)\n", jd->varcount, jd->vartop);
193 0 : if (stage >= SHOW_STACK)
194 0 : printf("Max interfaces: %d\n", jd->maxinterfaces);
195 0 : printf("Max locals: %d\n", jd->maxlocals);
196 0 : printf("Max stack: %d\n", m->maxstack);
197 0 : printf("Linenumbers: %d\n", m->linenumbercount);
198 0 : printf("Branch to entry: %s\n", (jd->branchtoentry) ? "yes" : "no");
199 0 : printf("Branch to end: %s\n", (jd->branchtoend) ? "yes" : "no");
200 0 : if (stage >= SHOW_STACK) {
201 0 : printf("Number of RETURNs: %d", jd->returncount);
202 0 : if (jd->returncount == 1)
203 0 : printf(" (block L%03d)", jd->returnblock->nr);
204 0 : printf("\n");
205 : }
206 :
207 0 : if (stage >= SHOW_PARSE) {
208 0 : printf("Exceptions (number=%d):\n", jd->exceptiontablelength);
209 0 : for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
210 0 : printf(" L%03d ... ", ex->start->nr );
211 0 : printf("L%03d = ", ex->end->nr);
212 0 : printf("L%03d", ex->handler->nr);
213 0 : printf(" (catchtype: ");
214 0 : if (ex->catchtype.any)
215 0 : if (ex->catchtype.is_classref())
216 0 : class_classref_print(ex->catchtype.ref);
217 : else
218 0 : class_print(ex->catchtype.cls);
219 : else
220 0 : printf("ANY");
221 0 : printf(")\n");
222 : }
223 : }
224 :
225 0 : if (irstage >= SHOW_PARSE && rd && jd->localcount > 0) {
226 0 : printf("Local Table:\n");
227 0 : for (i = 0; i < jd->localcount; i++) {
228 0 : printf(" %3d: ", i);
229 :
230 : #if defined(ENABLE_JIT)
231 : # if defined(ENABLE_INTRP)
232 : if (!opt_intrp) {
233 : # endif
234 0 : printf(" (%s) ", show_jit_type_names[VAR(i)->type]);
235 0 : if (irstage >= SHOW_REGS)
236 0 : show_allocation(VAR(i)->type, VAR(i)->flags, VAR(i)->vv.regoff);
237 0 : printf("\n");
238 : # if defined(ENABLE_INTRP)
239 : }
240 : # endif
241 : #endif /* defined(ENABLE_JIT) */
242 : }
243 0 : printf("\n");
244 : }
245 :
246 0 : if (jd->maxlocals > 0 && jd->local_map != NULL) {
247 0 : printf("Local Map:\n");
248 0 : printf(" index ");
249 0 : for (j = 0; j < jd->maxlocals; j++) {
250 0 : printf(" [%2d]", j);
251 : }
252 0 : printf("\n");
253 0 : for (i = 0; i < 5; i++) {
254 0 : printf(" %5s ",show_jit_type_names[i]);
255 0 : for (j = 0; j < jd->maxlocals; j++) {
256 0 : if (jd->local_map[j*5+i] == jitdata::UNUSED)
257 0 : printf(" -- ");
258 : else
259 0 : printf("%4i ",jd->local_map[j*5+i]);
260 : }
261 0 : printf("\n");
262 : }
263 0 : printf("\n");
264 : }
265 :
266 0 : if (jd->maxinterfaces > 0 && jd->interface_map && irstage >= SHOW_STACK) {
267 0 : bool exist = false;
268 0 : interface_info *mapptr = jd->interface_map;
269 :
270 : /* look if there exist any INOUTS */
271 0 : for (i = 0; (i < (5 * jd->maxinterfaces)) && !exist; i++, mapptr++)
272 0 : exist = (mapptr->flags != jitdata::UNUSED);
273 :
274 0 : if (exist) {
275 0 : printf("Interface Table: (In/Outvars)\n");
276 0 : printf(" depth ");
277 0 : for (j = 0; j < jd->maxinterfaces; j++) {
278 0 : printf(" [%2d]", j);
279 : }
280 0 : printf("\n");
281 :
282 0 : for (i = 0; i < 5; i++) {
283 0 : printf(" %5s ",show_jit_type_names[i]);
284 0 : for (j = 0; j < jd->maxinterfaces; j++) {
285 0 : s4 flags = jd->interface_map[j*5+i].flags;
286 0 : s4 regoff = jd->interface_map[j*5+i].regoff;
287 0 : if (flags == jitdata::UNUSED)
288 0 : printf(" -- ");
289 : else {
290 : int ch;
291 :
292 0 : if (irstage >= SHOW_REGS) {
293 0 : if (flags & SAVEDVAR) {
294 0 : if (flags & INMEMORY)
295 0 : ch = 'M';
296 : else
297 0 : ch = 'R';
298 : }
299 : else {
300 0 : if (flags & INMEMORY)
301 0 : ch = 'm';
302 : else
303 0 : ch = 'r';
304 : }
305 0 : printf("%c%03d(", ch, regoff);
306 0 : show_allocation(i, flags, regoff);
307 0 : printf(") ");
308 : }
309 : else {
310 0 : if (flags & SAVEDVAR)
311 0 : printf(" I ");
312 : else
313 0 : printf(" i ");
314 : }
315 : }
316 : }
317 0 : printf("\n");
318 : }
319 0 : printf("\n");
320 : }
321 : }
322 :
323 0 : if (rd->memuse && irstage >= SHOW_REGS) {
324 : int max;
325 :
326 0 : max = rd->memuse;
327 0 : printf("Stack slots (memuse=%d", rd->memuse);
328 0 : if (irstage >= SHOW_CODE) {
329 0 : printf(", stackframesize=%d", cd->stackframesize);
330 0 : max = cd->stackframesize;
331 : }
332 0 : printf("):\n");
333 0 : for (i = 0; i < max; ++i) {
334 0 : printf(" M%02d = 0x%02x(sp): ", i, i * 8);
335 0 : for (j = 0; j < jd->vartop; ++j) {
336 0 : varinfo *v = VAR(j);
337 0 : if ((v->flags & INMEMORY) && (v->vv.regoff == i)) {
338 0 : show_variable(jd, j, irstage);
339 0 : putchar(' ');
340 : }
341 : }
342 :
343 0 : printf("\n");
344 :
345 : }
346 0 : printf("\n");
347 : }
348 :
349 0 : if (!code->patchers->empty()) {
350 0 : int number = code->patchers->size();
351 0 : printf("Patcher References (number=%d):\n", number);
352 0 : patcher_list_show(code);
353 0 : printf("\n");
354 : }
355 :
356 : #if defined(ENABLE_REPLACEMENT)
357 : if (code->rplpoints) {
358 : printf("Replacement Points:\n");
359 : replace_show_replacement_points(code);
360 : printf("\n");
361 : }
362 : #endif /* defined(ENABLE_REPLACEMENT) */
363 :
364 : #if defined(ENABLE_DISASSEMBLER)
365 : /* show code before first basic block */
366 :
367 : if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
368 : pc = (u1 *) ((ptrint) code->mcode + cd->dseglen);
369 :
370 : for (; pc < (u1 *) ((ptrint) code->mcode + cd->dseglen + jd->basicblocks[0].mpc);)
371 : DISASSINSTR(pc);
372 :
373 : printf("\n");
374 : }
375 : #endif
376 :
377 : /* show code of all basic blocks */
378 :
379 0 : for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next)
380 0 : show_basicblock(jd, bptr, stage);
381 :
382 : #if 0 && defined(ENABLE_DISASSEMBLER)
383 : /* show code after last basic block */
384 :
385 : if (stage >= SHOW_CODE && opt_showdisassemble) {
386 : printf("\nStubs code:\n");
387 : printf("Length: %d\n\n", (s4) (code->mcodelength -
388 : ((ptrint) cd->dseglen + lastbptr->mpc)));
389 :
390 : pc = (u1 *) ((ptrint) code->mcode + cd->dseglen + lastbptr->mpc);
391 :
392 : for (; (ptrint) pc < ((ptrint) code->mcode + code->mcodelength);)
393 : DISASSINSTR(pc);
394 :
395 : printf("\n");
396 : }
397 : #endif
398 :
399 0 : mutex.unlock();
400 :
401 : /* finally flush the output */
402 :
403 0 : fflush(stdout);
404 0 : }
405 : #endif /* !defined(NDEBUG) */
406 :
407 :
408 : #if !defined(NDEBUG) && defined(ENABLE_INLINING)
409 : static void show_inline_info(jitdata *jd, insinfo_inline *ii, s4 opcode, s4 stage)
410 : {
411 : s4 *jl;
412 : s4 n;
413 :
414 : printf("(pt %d+%d+%d st ",
415 : ii->throughcount - (ii->stackvarscount - ii->paramcount),
416 : ii->stackvarscount - ii->paramcount,
417 : ii->paramcount);
418 : show_variable_array(jd, ii->stackvars, ii->stackvarscount, stage);
419 :
420 : if (opcode == ICMD_INLINE_START || opcode == ICMD_INLINE_END) {
421 : printf(" jl ");
422 : jl = (opcode == ICMD_INLINE_START) ? ii->javalocals_start : ii->javalocals_end;
423 : n = (opcode == ICMD_INLINE_START) ? ii->method->maxlocals : ii->outer->maxlocals;
424 : show_javalocals_array(jd, jl, n, stage);
425 : }
426 :
427 : printf(") ");
428 :
429 : #if 0
430 : printf("(");
431 : method_print(ii->outer);
432 : printf(" ==> ");
433 : #endif
434 :
435 : method_print(ii->method);
436 : }
437 : #endif /* !defined(NDEBUG) && defined(ENABLE_INLINING) */
438 :
439 :
440 : /* show_basicblock *************************************************************
441 :
442 : Print the intermediate representation of a basic block.
443 :
444 : NOTE: Currently this function may only be called after register allocation!
445 :
446 : *******************************************************************************/
447 :
448 : #if !defined(NDEBUG)
449 0 : void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
450 : {
451 : s4 i;
452 : bool deadcode;
453 : instruction *iptr;
454 : int irstage;
455 : #if defined(ENABLE_DISASSEMBLER)
456 : methodinfo *m; /* this is only a dummy */
457 : void *pc;
458 : s4 linenumber;
459 : s4 currentlinenumber;
460 : #endif
461 :
462 :
463 0 : if (bptr->state != basicblock::DELETED) {
464 : #if defined(ENABLE_INTRP)
465 : if (opt_intrp) {
466 : deadcode = false;
467 : irstage = SHOW_PARSE;
468 : }
469 : else
470 : #endif
471 : {
472 0 : deadcode = (bptr->state < basicblock::REACHED);
473 0 : irstage = stage;
474 : }
475 :
476 : printf("======== %sL%03d ======== %s(flags: %d, bitflags: %01x, next: %d, type: ",
477 : #if defined(ENABLE_REPLACEMENT)
478 : (bptr->bitflags & BBFLAG_REPLACEMENT) ? "<REPLACE> " :
479 : #endif
480 : "",
481 : bptr->nr,
482 : (deadcode && stage >= SHOW_STACK) ? "DEADCODE! " : "",
483 : bptr->state, bptr->bitflags,
484 0 : (bptr->next) ? (bptr->next->nr) : -1);
485 :
486 0 : switch (bptr->type) {
487 : case basicblock::TYPE_STD:
488 0 : printf("STD");
489 0 : break;
490 : case basicblock::TYPE_EXH:
491 0 : printf("EXH");
492 0 : break;
493 : case basicblock::TYPE_SBR:
494 0 : printf("SBR");
495 : break;
496 : }
497 :
498 0 : printf(", icount: %d", bptr->icount);
499 :
500 0 : if (irstage >= SHOW_CFG) {
501 0 : printf(", preds: %d [ ", bptr->predecessorcount);
502 :
503 0 : for (i = 0; i < bptr->predecessorcount; i++)
504 0 : printf("%d ", bptr->predecessors[i]->nr);
505 :
506 0 : printf("]");
507 : }
508 :
509 0 : printf("):");
510 :
511 0 : if (bptr->original)
512 0 : printf(" (clone of L%03d)", bptr->original->nr);
513 : else {
514 0 : basicblock *b = bptr->copied_to;
515 0 : if (b) {
516 0 : printf(" (copied to ");
517 0 : for (; b; b = b->copied_to)
518 0 : printf("L%03d ", b->nr);
519 0 : printf(")");
520 : }
521 : }
522 :
523 0 : printf("\n");
524 :
525 0 : if (irstage >= SHOW_CFG) {
526 0 : printf("succs: %d [ ", bptr->successorcount);
527 :
528 0 : for (i = 0; i < bptr->successorcount; i++)
529 0 : printf("%d ", bptr->successors[i]->nr);
530 :
531 0 : printf("]\n");
532 : }
533 :
534 0 : if (irstage >= SHOW_STACK) {
535 0 : printf("IN: ");
536 0 : show_variable_array(jd, bptr->invars, bptr->indepth, irstage);
537 0 : printf(" javalocals: ");
538 0 : if (bptr->javalocals)
539 0 : show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
540 : else
541 0 : printf("null");
542 0 : printf("\n");
543 : }
544 :
545 : #if defined(ENABLE_INLINING)
546 : if (bptr->inlineinfo) {
547 : printf("inlineinfo: ");
548 : show_inline_info(jd, bptr->inlineinfo, -1, irstage);
549 : printf("\n");
550 : }
551 : #endif /* defined(ENABLE_INLINING) */
552 :
553 : #if defined(ENABLE_SSA)
554 :
555 : iptr = bptr->phis;
556 :
557 : for (i = 0; i < bptr->phicount; i++, iptr++) {
558 : printf("%4d:%4d: ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
559 :
560 : show_icmd(jd, iptr, deadcode, irstage);
561 : printf("\n");
562 : }
563 : #endif
564 :
565 0 : iptr = bptr->iinstr;
566 :
567 0 : for (i = 0; i < bptr->icount; i++, iptr++) {
568 0 : printf("%4d:%4d: ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
569 :
570 0 : show_icmd(jd, iptr, deadcode, irstage);
571 0 : printf("\n");
572 : }
573 :
574 0 : if (irstage >= SHOW_STACK) {
575 0 : printf("OUT: ");
576 0 : show_variable_array(jd, bptr->outvars, bptr->outdepth, irstage);
577 0 : printf("\n");
578 : }
579 :
580 : #if defined(ENABLE_DISASSEMBLER)
581 : if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) &&
582 : (!deadcode))
583 : {
584 : codeinfo *code = jd->code;
585 : codegendata *cd = jd->cd;
586 :
587 : printf("\n");
588 : pc = (void *) (code->mcode + cd->dseglen + bptr->mpc);
589 : linenumber = 0;
590 :
591 : if (bptr->next != NULL) {
592 : for (; pc < (void *) (code->mcode + cd->dseglen + bptr->next->mpc);) {
593 : currentlinenumber = code->linenumbertable->find(&m, pc);
594 :
595 : if (currentlinenumber != linenumber) {
596 : linenumber = currentlinenumber;
597 : printf("%4d:\n", linenumber);
598 : }
599 :
600 : DISASSINSTR(pc);
601 : }
602 : }
603 : else {
604 : for (; pc < (void *) (code->mcode + code->mcodelength);) {
605 : currentlinenumber = code->linenumbertable->find(&m, pc);
606 :
607 : if (currentlinenumber != linenumber) {
608 : linenumber = currentlinenumber;
609 : printf("%4d:\n", linenumber);
610 : }
611 :
612 : DISASSINSTR(pc);
613 : }
614 : }
615 : printf("\n");
616 : }
617 : #endif
618 : }
619 0 : }
620 : #endif /* !defined(NDEBUG) */
621 :
622 :
623 : /* show_icmd *******************************************************************
624 :
625 : Print the intermediate representation of an instruction.
626 :
627 : NOTE: Currently this function may only be called after register allocation!
628 :
629 : *******************************************************************************/
630 :
631 : #if !defined(NDEBUG)
632 :
633 : #define SHOW_TARGET(target) \
634 : if (stage >= SHOW_PARSE) { \
635 : printf("--> L%03d ", (target).block->nr); \
636 : } \
637 : else { \
638 : printf("--> insindex %d ", (target).insindex); \
639 : }
640 :
641 : #define SHOW_INT_CONST(val) \
642 : if (stage >= SHOW_PARSE) { \
643 : printf("%d (0x%08x) ", (int32_t) (val), (int32_t) (val)); \
644 : } \
645 : else { \
646 : printf("iconst "); \
647 : }
648 :
649 : #define SHOW_LNG_CONST(val) \
650 : if (stage >= SHOW_PARSE) \
651 : printf("%" PRId64 " (0x%016" PRIx64 ") ", (val), (val)); \
652 : else \
653 : printf("lconst ");
654 :
655 : #define SHOW_ADR_CONST(val) \
656 : if (stage >= SHOW_PARSE) \
657 : printf("0x%" PRINTF_INTPTR_NUM_HEXDIGITS PRIxPTR " ", (ptrint) (val)); \
658 : else \
659 : printf("aconst ");
660 :
661 : #define SHOW_FLT_CONST(val) \
662 : if (stage >= SHOW_PARSE) { \
663 : imm_union v; \
664 : v.f = (val); \
665 : printf("%g (0x%08x) ", (val), v.i); \
666 : } \
667 : else { \
668 : printf("fconst "); \
669 : }
670 :
671 : #define SHOW_DBL_CONST(val) \
672 : if (stage >= SHOW_PARSE) { \
673 : imm_union v; \
674 : v.d = (val); \
675 : printf("%g (0x%016" PRIx64 ") ", (val), v.l); \
676 : } \
677 : else \
678 : printf("dconst ");
679 :
680 : #define SHOW_INDEX(index) \
681 : if (stage >= SHOW_PARSE) { \
682 : printf("%d ", index); \
683 : } \
684 : else { \
685 : printf("index"); \
686 : }
687 :
688 : #define SHOW_STRING(val) \
689 : if (stage >= SHOW_PARSE) { \
690 : putchar('"'); \
691 : utf_display_printable_ascii( \
692 : JavaString((java_handle_t*) (val)).to_utf8()); \
693 : printf("\" "); \
694 : } \
695 : else { \
696 : printf("string "); \
697 : }
698 :
699 : #define SHOW_CLASSREF_OR_CLASSINFO(c) \
700 : if (stage >= SHOW_PARSE) { \
701 : if (c.is_classref()) \
702 : class_classref_print(c.ref); \
703 : else \
704 : class_print(c.cls); \
705 : putchar(' '); \
706 : } \
707 : else { \
708 : printf("class "); \
709 : }
710 :
711 : #define SHOW_FIELD(fmiref) \
712 : if (stage >= SHOW_PARSE) { \
713 : field_fieldref_print(fmiref); \
714 : putchar(' '); \
715 : } \
716 : else { \
717 : printf("field "); \
718 : }
719 :
720 : #define SHOW_VARIABLE(v) \
721 : show_variable(jd, (v), stage)
722 :
723 : #define SHOW_S1(iptr) \
724 : if (stage >= SHOW_STACK) { \
725 : SHOW_VARIABLE(iptr->s1.varindex); \
726 : }
727 :
728 : #define SHOW_S2(iptr) \
729 : if (stage >= SHOW_STACK) { \
730 : SHOW_VARIABLE(iptr->sx.s23.s2.varindex); \
731 : }
732 :
733 : #define SHOW_S3(iptr) \
734 : if (stage >= SHOW_STACK) { \
735 : SHOW_VARIABLE(iptr->sx.s23.s3.varindex); \
736 : }
737 :
738 : #define SHOW_DST(iptr) \
739 : if (stage >= SHOW_STACK) { \
740 : printf("=> "); \
741 : SHOW_VARIABLE(iptr->dst.varindex); \
742 : }
743 :
744 : #define SHOW_S1_LOCAL(iptr) \
745 : if (stage >= SHOW_STACK) { \
746 : printf("L%d ", iptr->s1.varindex); \
747 : } \
748 : else { \
749 : printf("JavaL%d ", iptr->s1.varindex); \
750 : }
751 :
752 : #define SHOW_DST_LOCAL(iptr) \
753 : if (stage >= SHOW_STACK) { \
754 : printf("=> L%d ", iptr->dst.varindex); \
755 : } \
756 : else { \
757 : printf("=> JavaL%d ", iptr->dst.varindex); \
758 : }
759 :
760 0 : void show_allocation(s4 type, s4 flags, s4 regoff)
761 : {
762 0 : if (type == TYPE_RET) {
763 0 : printf("N/A");
764 0 : return;
765 : }
766 :
767 0 : if (flags & INMEMORY) {
768 0 : printf("M%02d", regoff);
769 0 : return;
770 : }
771 :
772 0 : if (IS_FLT_DBL_TYPE(type)) {
773 0 : printf("F%02d", regoff);
774 0 : return;
775 : }
776 :
777 : #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
778 : if (IS_2_WORD_TYPE(type)) {
779 : # if defined(ENABLE_JIT)
780 : # if defined(ENABLE_INTRP)
781 : if (opt_intrp)
782 : printf("%3d/%3d", GET_LOW_REG(regoff),
783 : GET_HIGH_REG(regoff));
784 : else
785 : # endif
786 : printf("%3s/%3s", abi_registers_integer_name[GET_LOW_REG(regoff)],
787 : abi_registers_integer_name[GET_HIGH_REG(regoff)]);
788 : # else
789 : printf("%3d/%3d", GET_LOW_REG(regoff),
790 : GET_HIGH_REG(regoff));
791 : # endif
792 : return;
793 : }
794 : #endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
795 :
796 : #if defined(ENABLE_JIT)
797 : # if defined(ENABLE_INTRP)
798 : if (opt_intrp)
799 : printf("%3d", regoff);
800 : else
801 : # endif
802 0 : printf("%3s", abi_registers_integer_name[regoff]);
803 : #else
804 : printf("%3d", regoff);
805 : #endif
806 : }
807 :
808 0 : void show_variable(jitdata *jd, s4 index, int stage)
809 : {
810 0 : show_variable_intern(jd, index, stage);
811 0 : putchar(' ');
812 0 : }
813 :
814 0 : static void show_variable_intern(jitdata *jd, s4 index, int stage)
815 : {
816 : char type;
817 : char kind;
818 : varinfo *v;
819 :
820 0 : if (index < 0 || index >= jd->vartop) {
821 0 : printf("<INVALID INDEX:%d>", index);
822 0 : return;
823 : }
824 :
825 0 : v = VAR(index);
826 :
827 0 : switch (v->type) {
828 0 : case TYPE_INT: type = 'i'; break;
829 0 : case TYPE_LNG: type = 'l'; break;
830 0 : case TYPE_FLT: type = 'f'; break;
831 0 : case TYPE_DBL: type = 'd'; break;
832 0 : case TYPE_ADR: type = 'a'; break;
833 0 : case TYPE_RET: type = 'r'; break;
834 0 : default: type = '?';
835 : }
836 :
837 0 : if (index < jd->localcount) {
838 0 : kind = 'L';
839 0 : if (v->flags & (PREALLOC | INOUT))
840 0 : printf("<INVALID FLAGS!>");
841 : }
842 : else {
843 0 : if (v->flags & PREALLOC) {
844 0 : kind = 'A';
845 0 : if (v->flags & INOUT) {
846 : /* PREALLOC is used to avoid allocation of TYPE_RET */
847 0 : if (v->type == TYPE_RET)
848 0 : kind = 'i';
849 : else
850 0 : printf("<INVALID FLAGS!>");
851 : }
852 : }
853 0 : else if (v->flags & INOUT)
854 0 : kind = 'I';
855 : else
856 0 : kind = 'T';
857 : }
858 :
859 0 : printf("%c%c%d", kind, type, index);
860 :
861 0 : if (v->flags & SAVEDVAR)
862 0 : putchar('!');
863 :
864 0 : if (stage >= SHOW_REGS || (v->flags & PREALLOC)) {
865 0 : putchar('(');
866 0 : show_allocation(v->type, v->flags, v->vv.regoff);
867 0 : putchar(')');
868 : }
869 :
870 0 : if (v->type == TYPE_RET && (v->flags & PREALLOC)) {
871 0 : printf("(L%03d)", v->vv.retaddr->nr);
872 : }
873 : }
874 :
875 0 : static void show_variable_array_intern(jitdata *jd, s4 *vars, int n, int stage,
876 : bool javalocals)
877 : {
878 : int i;
879 : int nr;
880 :
881 0 : if (vars == NULL) {
882 0 : printf("<null>");
883 0 : return;
884 : }
885 :
886 0 : printf("[");
887 0 : for (i=0; i<n; ++i) {
888 0 : if (i)
889 0 : putchar(' ');
890 0 : if (vars[i] < 0) {
891 0 : if (vars[i] == jitdata::UNUSED)
892 0 : putchar('-');
893 0 : else if (javalocals) {
894 0 : nr = RETADDR_FROM_JAVALOCAL(vars[i]);
895 0 : printf("ret(L%03d)", nr);
896 : }
897 : else {
898 0 : printf("<INVALID INDEX:%d>", vars[i]);
899 : }
900 : }
901 : else
902 0 : show_variable_intern(jd, vars[i], stage);
903 : }
904 0 : printf("]");
905 : }
906 :
907 0 : void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
908 : {
909 0 : show_variable_array_intern(jd, vars, n, stage, false);
910 0 : }
911 :
912 0 : void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage)
913 : {
914 0 : show_variable_array_intern(jd, vars, n, stage, true);
915 0 : }
916 :
917 0 : void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
918 : {
919 : branch_target_t *table;
920 : lookup_target_t *lookup;
921 : constant_FMIref *fmiref;
922 : s4 *argp;
923 : s4 i;
924 :
925 : /* get the opcode and the condition */
926 :
927 0 : ICMD opcode = iptr->opc;
928 :
929 0 : printf("%s ", icmd_table[opcode].name);
930 :
931 0 : if (stage < SHOW_PARSE)
932 0 : return;
933 :
934 0 : if (deadcode)
935 0 : stage = SHOW_PARSE;
936 :
937 : /* Print the condition for conditional instructions. */
938 :
939 : /* XXX print condition from flags */
940 :
941 0 : if (iptr->flags.bits & INS_FLAG_UNRESOLVED)
942 0 : printf("(UNRESOLVED) ");
943 :
944 0 : switch (opcode) {
945 :
946 : case ICMD_POP:
947 : case ICMD_CHECKNULL:
948 0 : SHOW_S1(iptr);
949 0 : break;
950 :
951 : /* unary */
952 : case ICMD_ARRAYLENGTH:
953 : case ICMD_INEG:
954 : case ICMD_LNEG:
955 : case ICMD_FNEG:
956 : case ICMD_DNEG:
957 : case ICMD_I2L:
958 : case ICMD_I2F:
959 : case ICMD_I2D:
960 : case ICMD_L2I:
961 : case ICMD_L2F:
962 : case ICMD_L2D:
963 : case ICMD_F2I:
964 : case ICMD_F2L:
965 : case ICMD_F2D:
966 : case ICMD_D2I:
967 : case ICMD_D2L:
968 : case ICMD_D2F:
969 : case ICMD_INT2BYTE:
970 : case ICMD_INT2CHAR:
971 : case ICMD_INT2SHORT:
972 0 : SHOW_S1(iptr);
973 0 : SHOW_DST(iptr);
974 0 : break;
975 :
976 : /* binary */
977 : case ICMD_IADD:
978 : case ICMD_LADD:
979 : case ICMD_FADD:
980 : case ICMD_DADD:
981 : case ICMD_ISUB:
982 : case ICMD_LSUB:
983 : case ICMD_FSUB:
984 : case ICMD_DSUB:
985 : case ICMD_IMUL:
986 : case ICMD_LMUL:
987 : case ICMD_FMUL:
988 : case ICMD_DMUL:
989 : case ICMD_IDIV:
990 : case ICMD_LDIV:
991 : case ICMD_FDIV:
992 : case ICMD_DDIV:
993 : case ICMD_IREM:
994 : case ICMD_LREM:
995 : case ICMD_FREM:
996 : case ICMD_DREM:
997 : case ICMD_ISHL:
998 : case ICMD_LSHL:
999 : case ICMD_ISHR:
1000 : case ICMD_LSHR:
1001 : case ICMD_IUSHR:
1002 : case ICMD_LUSHR:
1003 : case ICMD_IAND:
1004 : case ICMD_LAND:
1005 : case ICMD_IOR:
1006 : case ICMD_LOR:
1007 : case ICMD_IXOR:
1008 : case ICMD_LXOR:
1009 : case ICMD_LCMP:
1010 : case ICMD_FCMPL:
1011 : case ICMD_FCMPG:
1012 : case ICMD_DCMPL:
1013 : case ICMD_DCMPG:
1014 0 : SHOW_S1(iptr);
1015 0 : SHOW_S2(iptr);
1016 0 : SHOW_DST(iptr);
1017 0 : break;
1018 :
1019 : /* binary/const INT */
1020 : case ICMD_IADDCONST:
1021 : case ICMD_ISUBCONST:
1022 : case ICMD_IMULCONST:
1023 : case ICMD_IMULPOW2:
1024 : case ICMD_IDIVPOW2:
1025 : case ICMD_IREMPOW2:
1026 : case ICMD_IANDCONST:
1027 : case ICMD_IORCONST:
1028 : case ICMD_IXORCONST:
1029 : case ICMD_ISHLCONST:
1030 : case ICMD_ISHRCONST:
1031 : case ICMD_IUSHRCONST:
1032 : case ICMD_LSHLCONST:
1033 : case ICMD_LSHRCONST:
1034 : case ICMD_LUSHRCONST:
1035 0 : SHOW_S1(iptr);
1036 0 : SHOW_INT_CONST(iptr->sx.val.i);
1037 0 : SHOW_DST(iptr);
1038 0 : break;
1039 :
1040 : /* ?ASTORECONST (trinary/const INT) */
1041 : case ICMD_IASTORECONST:
1042 : case ICMD_BASTORECONST:
1043 : case ICMD_CASTORECONST:
1044 : case ICMD_SASTORECONST:
1045 0 : SHOW_S1(iptr);
1046 0 : SHOW_S2(iptr);
1047 0 : SHOW_INT_CONST(iptr->sx.s23.s3.constval);
1048 0 : break;
1049 :
1050 : /* const INT */
1051 : case ICMD_ICONST:
1052 0 : SHOW_INT_CONST(iptr->sx.val.i);
1053 0 : SHOW_DST(iptr);
1054 0 : break;
1055 :
1056 : /* binary/const LNG */
1057 : case ICMD_LADDCONST:
1058 : case ICMD_LSUBCONST:
1059 : case ICMD_LMULCONST:
1060 : case ICMD_LMULPOW2:
1061 : case ICMD_LDIVPOW2:
1062 : case ICMD_LREMPOW2:
1063 : case ICMD_LANDCONST:
1064 : case ICMD_LORCONST:
1065 : case ICMD_LXORCONST:
1066 0 : SHOW_S1(iptr);
1067 0 : SHOW_LNG_CONST(iptr->sx.val.l);
1068 0 : SHOW_DST(iptr);
1069 0 : break;
1070 :
1071 : /* trinary/const LNG (<= pointer size) */
1072 : case ICMD_LASTORECONST:
1073 0 : SHOW_S1(iptr);
1074 0 : SHOW_S2(iptr);
1075 0 : SHOW_ADR_CONST(iptr->sx.s23.s3.constval);
1076 0 : break;
1077 :
1078 : /* const LNG */
1079 : case ICMD_LCONST:
1080 0 : SHOW_LNG_CONST(iptr->sx.val.l);
1081 0 : SHOW_DST(iptr);
1082 0 : break;
1083 :
1084 : /* const FLT */
1085 : case ICMD_FCONST:
1086 0 : SHOW_FLT_CONST(iptr->sx.val.f);
1087 0 : SHOW_DST(iptr);
1088 0 : break;
1089 :
1090 : /* const DBL */
1091 : case ICMD_DCONST:
1092 0 : SHOW_DBL_CONST(iptr->sx.val.d);
1093 0 : SHOW_DST(iptr);
1094 0 : break;
1095 :
1096 : /* const ADR */
1097 : case ICMD_ACONST:
1098 0 : if (iptr->flags.bits & INS_FLAG_CLASS) {
1099 0 : SHOW_ADR_CONST(iptr->sx.val.anyptr);
1100 0 : SHOW_CLASSREF_OR_CLASSINFO(iptr->sx.val.c);
1101 : }
1102 0 : else if (iptr->sx.val.anyptr == NULL) {
1103 0 : printf("NULL ");
1104 : }
1105 : else {
1106 0 : SHOW_ADR_CONST(iptr->sx.val.anyptr);
1107 0 : SHOW_STRING(iptr->sx.val.stringconst);
1108 : }
1109 0 : SHOW_DST(iptr);
1110 0 : break;
1111 :
1112 : case ICMD_AASTORECONST:
1113 0 : SHOW_S1(iptr);
1114 0 : SHOW_S2(iptr);
1115 0 : printf("%p ", (void*) iptr->sx.s23.s3.constval);
1116 0 : break;
1117 :
1118 : case ICMD_GETFIELD: /* 1 -> 1 */
1119 : case ICMD_PUTFIELD: /* 2 -> 0 */
1120 : case ICMD_PUTSTATIC: /* 1 -> 0 */
1121 : case ICMD_GETSTATIC: /* 0 -> 1 */
1122 : case ICMD_PUTSTATICCONST: /* 0 -> 0 */
1123 : case ICMD_PUTFIELDCONST: /* 1 -> 0 */
1124 0 : if (opcode != ICMD_GETSTATIC && opcode != ICMD_PUTSTATICCONST) {
1125 0 : SHOW_S1(iptr);
1126 0 : if (opcode == ICMD_PUTFIELD) {
1127 0 : SHOW_S2(iptr);
1128 : }
1129 : }
1130 0 : INSTRUCTION_GET_FIELDREF(iptr, fmiref);
1131 0 : SHOW_FIELD(fmiref);
1132 :
1133 0 : if (opcode == ICMD_GETSTATIC || opcode == ICMD_GETFIELD) {
1134 0 : SHOW_DST(iptr);
1135 : }
1136 0 : break;
1137 :
1138 : case ICMD_IINC:
1139 0 : SHOW_S1_LOCAL(iptr);
1140 0 : SHOW_INT_CONST(iptr->sx.val.i);
1141 0 : SHOW_DST_LOCAL(iptr);
1142 0 : break;
1143 :
1144 : case ICMD_IASTORE:
1145 : case ICMD_SASTORE:
1146 : case ICMD_BASTORE:
1147 : case ICMD_CASTORE:
1148 : case ICMD_LASTORE:
1149 : case ICMD_DASTORE:
1150 : case ICMD_FASTORE:
1151 : case ICMD_AASTORE:
1152 0 : SHOW_S1(iptr);
1153 0 : SHOW_S2(iptr);
1154 0 : SHOW_S3(iptr);
1155 0 : break;
1156 :
1157 : case ICMD_IALOAD:
1158 : case ICMD_SALOAD:
1159 : case ICMD_BALOAD:
1160 : case ICMD_CALOAD:
1161 : case ICMD_LALOAD:
1162 : case ICMD_DALOAD:
1163 : case ICMD_FALOAD:
1164 : case ICMD_AALOAD:
1165 0 : SHOW_S1(iptr);
1166 0 : SHOW_S2(iptr);
1167 0 : SHOW_DST(iptr);
1168 0 : break;
1169 :
1170 : case ICMD_RET:
1171 0 : SHOW_S1_LOCAL(iptr);
1172 0 : if (stage >= SHOW_STACK) {
1173 0 : printf(" ---> L%03d", iptr->dst.block->nr);
1174 : }
1175 0 : break;
1176 :
1177 : case ICMD_ILOAD:
1178 : case ICMD_LLOAD:
1179 : case ICMD_FLOAD:
1180 : case ICMD_DLOAD:
1181 : case ICMD_ALOAD:
1182 0 : SHOW_S1_LOCAL(iptr);
1183 0 : SHOW_DST(iptr);
1184 0 : break;
1185 :
1186 : case ICMD_ISTORE:
1187 : case ICMD_LSTORE:
1188 : case ICMD_FSTORE:
1189 : case ICMD_DSTORE:
1190 : case ICMD_ASTORE:
1191 0 : SHOW_S1(iptr);
1192 0 : SHOW_DST_LOCAL(iptr);
1193 0 : if (stage >= SHOW_STACK && iptr->sx.s23.s3.javaindex != jitdata::UNUSED)
1194 0 : printf(" (javaindex %d)", iptr->sx.s23.s3.javaindex);
1195 0 : if (iptr->flags.bits & INS_FLAG_RETADDR) {
1196 0 : printf(" (retaddr L%03d)", RETADDR_FROM_JAVALOCAL(iptr->sx.s23.s2.retaddrnr));
1197 : }
1198 0 : break;
1199 :
1200 : case ICMD_NEW:
1201 0 : SHOW_DST(iptr);
1202 0 : break;
1203 :
1204 : case ICMD_NEWARRAY:
1205 0 : SHOW_DST(iptr);
1206 0 : break;
1207 :
1208 : case ICMD_ANEWARRAY:
1209 0 : SHOW_DST(iptr);
1210 0 : break;
1211 :
1212 : case ICMD_MULTIANEWARRAY:
1213 0 : if (stage >= SHOW_STACK) {
1214 0 : argp = iptr->sx.s23.s2.args;
1215 0 : i = iptr->s1.argcount;
1216 0 : while (i--) {
1217 0 : SHOW_VARIABLE(*(argp++));
1218 : }
1219 : }
1220 : else {
1221 0 : printf("argcount=%d ", iptr->s1.argcount);
1222 : }
1223 0 : class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
1224 0 : putchar(' ');
1225 0 : SHOW_DST(iptr);
1226 0 : break;
1227 :
1228 : case ICMD_CHECKCAST:
1229 0 : SHOW_S1(iptr);
1230 0 : class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
1231 0 : putchar(' ');
1232 0 : SHOW_DST(iptr);
1233 0 : break;
1234 :
1235 : case ICMD_INSTANCEOF:
1236 0 : SHOW_S1(iptr);
1237 0 : SHOW_DST(iptr);
1238 0 : break;
1239 :
1240 : case ICMD_INLINE_START:
1241 : case ICMD_INLINE_END:
1242 : case ICMD_INLINE_BODY:
1243 : #if defined(ENABLE_INLINING)
1244 : {
1245 : insinfo_inline *ii = iptr->sx.s23.s3.inlineinfo;
1246 : show_inline_info(jd, ii, opcode, stage);
1247 : }
1248 : #endif
1249 0 : break;
1250 :
1251 : case ICMD_BUILTIN:
1252 0 : if (stage >= SHOW_STACK) {
1253 0 : argp = iptr->sx.s23.s2.args;
1254 0 : i = iptr->s1.argcount;
1255 0 : while (i--) {
1256 0 : if ((iptr->s1.argcount - 1 - i) == iptr->sx.s23.s3.bte->md->paramcount)
1257 0 : printf(" pass-through: ");
1258 0 : SHOW_VARIABLE(*(argp++));
1259 : }
1260 : }
1261 0 : printf("%s ", iptr->sx.s23.s3.bte->cname);
1262 0 : if (iptr->sx.s23.s3.bte->md->returntype.type != TYPE_VOID) {
1263 0 : SHOW_DST(iptr);
1264 : }
1265 0 : break;
1266 :
1267 : case ICMD_INVOKEVIRTUAL:
1268 : case ICMD_INVOKESPECIAL:
1269 : case ICMD_INVOKESTATIC:
1270 : case ICMD_INVOKEINTERFACE:
1271 0 : if (stage >= SHOW_STACK) {
1272 : methoddesc *md;
1273 0 : INSTRUCTION_GET_METHODDESC(iptr, md);
1274 0 : argp = iptr->sx.s23.s2.args;
1275 0 : i = iptr->s1.argcount;
1276 0 : while (i--) {
1277 0 : if ((iptr->s1.argcount - 1 - i) == md->paramcount)
1278 0 : printf(" pass-through: ");
1279 0 : SHOW_VARIABLE(*(argp++));
1280 : }
1281 : }
1282 0 : INSTRUCTION_GET_METHODREF(iptr, fmiref);
1283 0 : method_methodref_print(fmiref);
1284 0 : if (fmiref->parseddesc.md->returntype.type != TYPE_VOID) {
1285 0 : putchar(' ');
1286 0 : SHOW_DST(iptr);
1287 : }
1288 0 : break;
1289 :
1290 : case ICMD_IFEQ:
1291 : case ICMD_IFNE:
1292 : case ICMD_IFLT:
1293 : case ICMD_IFGE:
1294 : case ICMD_IFGT:
1295 : case ICMD_IFLE:
1296 0 : SHOW_S1(iptr);
1297 0 : SHOW_INT_CONST(iptr->sx.val.i);
1298 0 : SHOW_TARGET(iptr->dst);
1299 0 : break;
1300 :
1301 : case ICMD_IF_LEQ:
1302 : case ICMD_IF_LNE:
1303 : case ICMD_IF_LLT:
1304 : case ICMD_IF_LGE:
1305 : case ICMD_IF_LGT:
1306 : case ICMD_IF_LLE:
1307 0 : SHOW_S1(iptr);
1308 0 : SHOW_LNG_CONST(iptr->sx.val.l);
1309 0 : SHOW_TARGET(iptr->dst);
1310 0 : break;
1311 :
1312 : case ICMD_GOTO:
1313 0 : SHOW_TARGET(iptr->dst);
1314 0 : break;
1315 :
1316 : case ICMD_JSR:
1317 0 : SHOW_TARGET(iptr->sx.s23.s3.jsrtarget);
1318 0 : SHOW_DST(iptr);
1319 0 : break;
1320 :
1321 : case ICMD_IFNULL:
1322 : case ICMD_IFNONNULL:
1323 0 : SHOW_S1(iptr);
1324 0 : SHOW_TARGET(iptr->dst);
1325 0 : break;
1326 :
1327 : case ICMD_IF_ICMPEQ:
1328 : case ICMD_IF_ICMPNE:
1329 : case ICMD_IF_ICMPLT:
1330 : case ICMD_IF_ICMPGE:
1331 : case ICMD_IF_ICMPGT:
1332 : case ICMD_IF_ICMPLE:
1333 :
1334 : case ICMD_IF_LCMPEQ:
1335 : case ICMD_IF_LCMPNE:
1336 : case ICMD_IF_LCMPLT:
1337 : case ICMD_IF_LCMPGE:
1338 : case ICMD_IF_LCMPGT:
1339 : case ICMD_IF_LCMPLE:
1340 :
1341 : case ICMD_IF_ACMPEQ:
1342 : case ICMD_IF_ACMPNE:
1343 0 : SHOW_S1(iptr);
1344 0 : SHOW_S2(iptr);
1345 0 : SHOW_TARGET(iptr->dst);
1346 0 : break;
1347 :
1348 : case ICMD_TABLESWITCH:
1349 0 : SHOW_S1(iptr);
1350 0 : table = iptr->dst.table;
1351 :
1352 0 : i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
1353 :
1354 0 : printf("high=%d low=%d count=%d\n", iptr->sx.s23.s3.tablehigh, iptr->sx.s23.s2.tablelow, i);
1355 0 : while (--i >= 0) {
1356 0 : printf("\t\t%d --> ", (int) (table - iptr->dst.table));
1357 0 : printf("L%03d\n", table->block->nr);
1358 0 : table++;
1359 : }
1360 :
1361 0 : break;
1362 :
1363 : case ICMD_LOOKUPSWITCH:
1364 0 : SHOW_S1(iptr);
1365 :
1366 : printf("count=%d, default=L%03d\n",
1367 : iptr->sx.s23.s2.lookupcount,
1368 0 : iptr->sx.s23.s3.lookupdefault.block->nr);
1369 :
1370 0 : lookup = iptr->dst.lookup;
1371 0 : i = iptr->sx.s23.s2.lookupcount;
1372 :
1373 0 : while (--i >= 0) {
1374 : printf("\t\t%d --> L%03d\n",
1375 : lookup->value,
1376 0 : lookup->target.block->nr);
1377 0 : lookup++;
1378 : }
1379 0 : break;
1380 :
1381 : case ICMD_FRETURN:
1382 : case ICMD_IRETURN:
1383 : case ICMD_DRETURN:
1384 : case ICMD_LRETURN:
1385 0 : SHOW_S1(iptr);
1386 0 : break;
1387 :
1388 : case ICMD_ARETURN:
1389 : case ICMD_ATHROW:
1390 0 : SHOW_S1(iptr);
1391 0 : if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1392 : /* XXX this needs more work */
1393 : #if 0
1394 : unresolved_class_debug_dump(iptr->sx.s23.s2.uc, stdout);
1395 : #endif
1396 : }
1397 0 : break;
1398 :
1399 : case ICMD_COPY:
1400 : case ICMD_MOVE:
1401 0 : SHOW_S1(iptr);
1402 0 : SHOW_DST(iptr);
1403 0 : break;
1404 : case ICMD_GETEXCEPTION:
1405 0 : SHOW_DST(iptr);
1406 : break;
1407 : #if defined(ENABLE_SSA)
1408 : case ICMD_PHI:
1409 : printf("[ ");
1410 : for (i = 0; i < iptr->s1.argcount; ++i) {
1411 : SHOW_VARIABLE(iptr->sx.s23.s2.iargs[i]->dst.varindex);
1412 : }
1413 : printf("] ");
1414 : SHOW_DST(iptr);
1415 : if (iptr->flags.bits & (1 << 0)) printf("used ");
1416 : if (iptr->flags.bits & (1 << 1)) printf("redundantAll ");
1417 : if (iptr->flags.bits & (1 << 2)) printf("redundantOne ");
1418 : break;
1419 : #endif
1420 : // ignore other ICMDs
1421 : default:
1422 : break;
1423 : }
1424 0 : fflush(stdout);
1425 : }
1426 : #endif /* !defined(NDEBUG) */
1427 :
1428 : /* Debug output filtering */
1429 :
1430 : #if defined(ENABLE_DEBUG_FILTER)
1431 :
1432 : struct show_filter {
1433 : /* Boolean indicating if filter is enabled. */
1434 : u1 enabled;
1435 : /* Regular expression the method name is matched against */
1436 : regex_t regex;
1437 : /* Flag set on m->filtermatches if regex matches */
1438 : u1 flag;
1439 : };
1440 :
1441 : typedef struct show_filter show_filter_t;
1442 :
1443 : #define SHOW_FILTERS_SIZE 3
1444 :
1445 : /* Array of filters applyed on a method */
1446 : static struct show_filter show_filters[SHOW_FILTERS_SIZE];
1447 :
1448 489 : static void show_filter_init(show_filter_t *cf, const char *str, u1 flag, u1 default_flag, const char *description) {
1449 : int err;
1450 : char err_buf[128];
1451 :
1452 489 : if (str) {
1453 0 : err = regcomp(&cf->regex, str, REG_EXTENDED | REG_NOSUB);
1454 0 : if (err != 0) {
1455 0 : regerror(err, &cf->regex, err_buf, sizeof(err_buf));
1456 : vm_abort(
1457 : "Invalid value given for %s: `%s' (%s).",
1458 : description, str, err_buf
1459 0 : );
1460 : }
1461 0 : cf->flag = flag;
1462 0 : cf->enabled = 1;
1463 : } else {
1464 489 : cf->flag = default_flag;
1465 489 : cf->enabled = 0;
1466 : }
1467 489 : }
1468 :
1469 163 : void show_filters_init(void) {
1470 :
1471 : show_filter_init(
1472 : show_filters + 0,
1473 : opt_filter_verbosecall_include,
1474 : SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
1475 : SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
1476 : "verbose call include filter"
1477 163 : );
1478 :
1479 : show_filter_init(
1480 : show_filters + 1,
1481 : opt_filter_verbosecall_exclude,
1482 : SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE,
1483 : 0,
1484 : "verbose call exclude filter"
1485 163 : );
1486 :
1487 : show_filter_init(
1488 : show_filters + 2,
1489 : opt_filter_show_method,
1490 : SHOW_FILTER_FLAG_SHOW_METHOD,
1491 : SHOW_FILTER_FLAG_SHOW_METHOD,
1492 : "show method filter"
1493 163 : );
1494 163 : }
1495 :
1496 : /*
1497 :
1498 : (Pseudo)State machine:
1499 :
1500 : States are INITIAL, INCLUDE1, INCLUDE2, ..., EXCLUDE1, ..., EXCLUDE2, ...
1501 :
1502 : Enter Enter
1503 : Enter Include Include
1504 : Exclude | | | |
1505 : | | Enter Enter Enter | | Enter | |
1506 : | | Include Include Exclude | | Exclude | |
1507 : | v ---------> ----------> ----------> | v ----------> | v
1508 : INITIAL INCLUDE1 INCLUDE2 EXCLUDE1 EXCLUDE2
1509 : | ^ <--------- <---------- <---------- | ^ <---------- | ^
1510 : | | Exit Exit Exit | | Exit | |
1511 : | | Include Include Exclude | | Exclude | |
1512 : | | | | | |
1513 : Exit Exit Exit
1514 : Exclude Include Include
1515 :
1516 : Verbose call scope is active if we are in a INCLUDE state.
1517 :
1518 : State encoding:
1519 :
1520 : INITIAL: ctr[0] == 0, ctr[1] == 0
1521 : INCLUDEN: ctr[1] == N, ctr[1] == 0
1522 : EXCLUDEN: ctr[1] == N
1523 : */
1524 :
1525 92267 : void show_filters_apply(methodinfo *m) {
1526 : // compose full name of method
1527 92267 : Buffer<> buf;
1528 :
1529 : const char *method_name = buf.write_slash_to_dot(m->clazz->name)
1530 : .write('.')
1531 : .write(m->name)
1532 : .write(m->descriptor)
1533 92267 : .c_str();
1534 :
1535 : /* reset all flags */
1536 :
1537 92267 : m->filtermatches = 0;
1538 :
1539 369068 : for (int i = 0; i < SHOW_FILTERS_SIZE; ++i) {
1540 276801 : if (show_filters[i].enabled) {
1541 :
1542 0 : int res = regexec(&show_filters[i].regex, method_name, 0, NULL, 0);
1543 :
1544 0 : if (res == 0) {
1545 0 : m->filtermatches |= show_filters[i].flag;
1546 : }
1547 : } else {
1548 : /* Default is to show all */
1549 276801 : m->filtermatches |= show_filters[i].flag;
1550 : }
1551 0 : }
1552 92267 : }
1553 :
1554 : #define STATE_IS_INITIAL() ((FILTERVERBOSECALLCTR[0] == 0) && (FILTERVERBOSECALLCTR[1] == 0))
1555 : #define STATE_IS_INCLUDE() ((FILTERVERBOSECALLCTR[0] > 0) && (FILTERVERBOSECALLCTR[1] == 0))
1556 : #define STATE_IS_EXCLUDE() (FILTERVERBOSECALLCTR[1] > 0)
1557 : #define EVENT_INCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE)
1558 : #define EVENT_EXCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE)
1559 : #define TRANSITION_NEXT_INCLUDE() ++FILTERVERBOSECALLCTR[0]
1560 : #define TRANSITION_PREV_INCLUDE() --FILTERVERBOSECALLCTR[0]
1561 : #define TRANSITION_NEXT_EXCLUDE() ++FILTERVERBOSECALLCTR[1]
1562 : #define TRANSITION_PREV_EXCLUDE() --FILTERVERBOSECALLCTR[1]
1563 :
1564 : #if 0
1565 : void dump_state() {
1566 : if (STATE_IS_INITIAL()) printf("<INITIAL>\n");
1567 : else if (STATE_IS_INCLUDE()) printf("<INCLUDE %hd>\n", FILTERVERBOSECALLCTR[0]);
1568 : else if (STATE_IS_EXCLUDE()) printf("<EXCLUDE %hd>\n", FILTERVERBOSECALLCTR[1]);
1569 : }
1570 : #endif
1571 :
1572 0 : int show_filters_test_verbosecall_enter(methodinfo *m) {
1573 :
1574 0 : int force_show = 0;
1575 :
1576 0 : if (STATE_IS_INITIAL()) {
1577 0 : if (EVENT_INCLUDE()) {
1578 0 : TRANSITION_NEXT_INCLUDE();
1579 : }
1580 0 : } else if (STATE_IS_INCLUDE()) {
1581 0 : if (EVENT_EXCLUDE()) {
1582 0 : TRANSITION_NEXT_EXCLUDE();
1583 : /* just entered exclude, show this method */
1584 0 : force_show = 1;
1585 0 : } else if (EVENT_INCLUDE()) {
1586 0 : TRANSITION_NEXT_INCLUDE();
1587 : }
1588 0 : } else if (STATE_IS_EXCLUDE()) {
1589 0 : if (EVENT_EXCLUDE()) {
1590 0 : TRANSITION_NEXT_EXCLUDE();
1591 : }
1592 : }
1593 :
1594 0 : return STATE_IS_INCLUDE() || force_show;
1595 : }
1596 :
1597 20521 : int show_filters_test_verbosecall_exit(methodinfo *m) {
1598 :
1599 20521 : int force_show = 0;
1600 :
1601 20521 : if (m) {
1602 20521 : if (STATE_IS_INCLUDE()) {
1603 0 : if (EVENT_INCLUDE()) {
1604 0 : TRANSITION_PREV_INCLUDE();
1605 : /* just entered initial, show this method */
1606 0 : if (STATE_IS_INITIAL()) force_show = 1;
1607 : }
1608 20521 : } else if (STATE_IS_EXCLUDE()) {
1609 0 : if (EVENT_EXCLUDE()) {
1610 0 : TRANSITION_PREV_EXCLUDE();
1611 : }
1612 : }
1613 : }
1614 :
1615 20521 : return STATE_IS_INCLUDE() || force_show;
1616 495 : }
1617 :
1618 : #endif
1619 :
1620 :
1621 : /*
1622 : * These are local overrides for various environment variables in Emacs.
1623 : * Please do not remove this and leave it at the end of the file, where
1624 : * Emacs will automagically detect them.
1625 : * ---------------------------------------------------------------------
1626 : * Local variables:
1627 : * mode: c++
1628 : * indent-tabs-mode: t
1629 : * c-basic-offset: 4
1630 : * tab-width: 4
1631 : * End:
1632 : * vim:noexpandtab:sw=4:ts=4:
1633 : */
|