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