1 /* -*- mode: c; tab-width: 4; c-basic-offset: 4 -*- */
2 /****************************** ncomp/nstack.c *********************************
4 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
6 See file COPYRIGHT for information on usage and disclaimer of warranties
8 Parser for JavaVM to intermediate code translation
10 Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
12 Last Change: 1997/11/18
14 *******************************************************************************/
16 #define CONDITIONAL_LOADCONST
19 #define COUNT(cnt) cnt++
24 #define STACKRESET {curstack=0;stackdepth=0;}
26 #define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");}
27 #define CURKIND curstack->varkind
28 #define CURTYPE curstack->type
30 #define NEWSTACK(s,v,n) {new->prev=curstack;new->type=s;new->flags=0;\
31 new->varkind=v;new->varnum=n;curstack=new;new++;}
32 #define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
33 #define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
34 #define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
36 #define SETDST {iptr->dst=curstack;}
37 #define POP(s) {if(s!=curstack->type){TYPEPANIC;}\
38 if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
39 curstack=curstack->prev;}
40 #define POPANY {if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
41 curstack=curstack->prev;}
42 #define COPY(s,d) {(d)->flags=0;(d)->type=(s)->type;\
43 (d)->varkind=(s)->varkind;(d)->varnum=(s)->varnum;}
45 #define CONST(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
46 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
47 #define STORE(s) {POP(s);SETDST;stackdepth--;}
48 #define OP1_0(s) {POP(s);SETDST;stackdepth--;}
49 #define OP1_0ANY {POPANY;SETDST;stackdepth--;}
50 #define OP0_1(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
51 #define OP1_1(s,d) {POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
52 #define OP2_0(s) {POP(s);POP(s);SETDST;stackdepth-=2;}
53 #define OPTT2_0(t,b){POP(t);POP(b);SETDST;stackdepth-=2;}
54 #define OP2_1(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
55 #define OP2IAT_1(s) {POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
57 #define OP2IT_1(s) {POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
59 #define OPTT2_1(s,d){POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
60 #define OP2_2(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
61 NEWSTACKn(s,stackdepth-1);SETDST;}
62 #define OP3TIA_0(s) {POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
63 #define OP3_0(s) {POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
64 #define POPMANY(i) {stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
65 #define DUP {NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST;\
67 #define SWAP {COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
68 new[0].prev=curstack;new[1].prev=new;\
69 curstack=new+1;new+=2;SETDST;}
70 #define DUP_X1 {COPY(curstack,new);COPY(curstack,new+2);POPANY;\
71 COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
72 new[1].prev=new;new[2].prev=new+1;\
73 curstack=new+2;new+=3;SETDST;stackdepth++;}
74 #define DUP2_X1 {COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
75 COPY(curstack,new);COPY(curstack,new+3);POPANY;\
76 COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
77 new[1].prev=new;new[2].prev=new+1;\
78 new[3].prev=new+2;new[4].prev=new+3;\
79 curstack=new+4;new+=5;SETDST;stackdepth+=2;}
80 #define DUP_X2 {COPY(curstack,new);COPY(curstack,new+3);POPANY;\
81 COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
82 new[0].prev=curstack;new[1].prev=new;\
83 new[2].prev=new+1;new[3].prev=new+2;\
84 curstack=new+3;new+=4;SETDST;stackdepth++;}
85 #define DUP2_X2 {COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
86 COPY(curstack,new);COPY(curstack,new+4);POPANY;\
87 COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
88 new[0].prev=curstack;new[1].prev=new;\
89 new[2].prev=new+1;new[3].prev=new+2;\
90 new[4].prev=new+3;new[5].prev=new+4;\
91 curstack=new+5;new+=6;SETDST;stackdepth+=2;}
93 #define COPYCURSTACK(copy) {\
106 copy->varkind=STACKVAR;\
122 if((copy->varkind==STACKVAR)&&(copy->varnum>i))\
123 copy->varkind=TEMPVAR;\
125 copy->varkind=STACKVAR;\
128 interfaces[i][copy->type].type = copy->type;\
129 interfaces[i][copy->type].flags |= copy->flags;\
130 i--;copy=copy->prev;\
135 interfaces[i][copy->type].type = copy->type;\
136 if(copy->varkind==STACKVAR){\
137 if (copy->flags & SAVEDVAR)\
138 interfaces[i][copy->type].flags |= SAVEDVAR;\
140 i--;copy=copy->prev;\
145 #define MARKREACHED(b,c) {\
147 {COPYCURSTACK(c);b->flags=0;b->instack=c;b->indepth=stackdepth;}\
148 else {stackptr s=curstack;stackptr t=b->instack;\
149 if(b->indepth!=stackdepth)\
150 {show_icmd_method();panic("Stack depth mismatch");}\
151 while(s){if (s->type!=t->type)\
153 s=s->prev;t=t->prev;\
159 static void show_icmd_method();
161 static void analyse_stack()
163 int b_count, b_index;
165 stackptr curstack, new, copy;
166 int opcode, i, len, loops;
167 int superblockend, repeat, deadcode;
168 instruction *iptr = instr;
169 basicblock *bptr, *tbptr;
175 block[0].flags = BBREACHED;
176 block[0].instack = 0;
177 block[0].indepth = 0;
179 for (i = 0; i < exceptiontablelength; i++) {
180 bptr = &block[block_index[extable[i].handlerpc]];
181 bptr->flags = BBREACHED;
182 bptr->type = BBTYPE_EXH;
185 bptr->pre_count = 10000;
190 #ifdef CONDITIONAL_LOADCONST
191 b_count = block_count;
193 while (--b_count >= 0) {
194 if (bptr[1].ipc > bptr[0].ipc) {
195 iptr = instr + bptr[1].ipc - 1;
228 block[block_index[iptr->op1]].pre_count++;
231 case ICMD_TABLESWITCH:
233 block[block_index[*s4ptr++]].pre_count++; /* default */
234 i = *s4ptr++; /* low */
235 i = *s4ptr++ - i + 1; /* high */
237 block[block_index[*s4ptr++]].pre_count++;
241 case ICMD_LOOKUPSWITCH:
243 block[block_index[*s4ptr++]].pre_count++; /* default */
244 i = *s4ptr++; /* count */
246 block[block_index[s4ptr[1]]].pre_count++;
262 b_count = block_count;
264 superblockend = true;
268 while (--b_count >= 0) {
269 if (bptr->flags == BBDELETED) {
272 else if (superblockend && (bptr->flags < BBREACHED))
274 else if (bptr->flags <= BBREACHED) {
276 stackdepth = bptr->indepth;
277 else if (bptr->flags < BBREACHED) {
279 bptr->instack = copy;
280 bptr->indepth = stackdepth;
282 else if (bptr->indepth != stackdepth) {
284 panic("Stack depth mismatch");
287 curstack = bptr->instack;
289 superblockend = false;
290 bptr->flags = BBFINISHED;
292 len = bptr[1].ipc - i;
294 b_index = bptr - block;
302 case ICMD_CHECKASIZE:
304 case ICMD_IFEQ_ICONST:
305 case ICMD_IFNE_ICONST:
306 case ICMD_IFLT_ICONST:
307 case ICMD_IFGE_ICONST:
308 case ICMD_IFGT_ICONST:
309 case ICMD_IFLE_ICONST:
310 case ICMD_ELSE_ICONST:
315 locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
317 COUNT(count_pcmd_return);
319 superblockend = true;
322 /* pop 0 push 1 const */
325 COUNT(count_pcmd_load);
327 switch (iptr[1].opc) {
329 iptr[0].opc = ICMD_IADDCONST;
331 iptr[1].opc = ICMD_NOP;
332 OP1_1(TYPE_INT,TYPE_INT);
333 COUNT(count_pcmd_op);
336 iptr[0].opc = ICMD_ISUBCONST;
337 goto icmd_iconst_tail;
339 iptr[0].opc = ICMD_IMULCONST;
340 goto icmd_iconst_tail;
342 if (iptr[0].val.i == 0x00000002)
344 else if (iptr[0].val.i == 0x00000004)
346 else if (iptr[0].val.i == 0x00000008)
348 else if (iptr[0].val.i == 0x00000010)
350 else if (iptr[0].val.i == 0x00000020)
352 else if (iptr[0].val.i == 0x00000040)
354 else if (iptr[0].val.i == 0x00000080)
356 else if (iptr[0].val.i == 0x00000100)
358 else if (iptr[0].val.i == 0x00000200)
360 else if (iptr[0].val.i == 0x00000400)
362 else if (iptr[0].val.i == 0x00000800)
364 else if (iptr[0].val.i == 0x00001000)
366 else if (iptr[0].val.i == 0x00002000)
368 else if (iptr[0].val.i == 0x00004000)
370 else if (iptr[0].val.i == 0x00008000)
372 else if (iptr[0].val.i == 0x00010000)
374 else if (iptr[0].val.i == 0x00020000)
376 else if (iptr[0].val.i == 0x00040000)
378 else if (iptr[0].val.i == 0x00080000)
380 else if (iptr[0].val.i == 0x00100000)
382 else if (iptr[0].val.i == 0x00200000)
384 else if (iptr[0].val.i == 0x00400000)
386 else if (iptr[0].val.i == 0x00800000)
388 else if (iptr[0].val.i == 0x01000000)
390 else if (iptr[0].val.i == 0x02000000)
392 else if (iptr[0].val.i == 0x04000000)
394 else if (iptr[0].val.i == 0x08000000)
396 else if (iptr[0].val.i == 0x10000000)
398 else if (iptr[0].val.i == 0x20000000)
400 else if (iptr[0].val.i == 0x40000000)
402 else if (iptr[0].val.i == 0x80000000)
408 iptr[0].opc = ICMD_IDIVPOW2;
409 goto icmd_iconst_tail;
411 if (iptr[0].val.i == 0x10001) {
412 iptr[0].opc = ICMD_IREM0X10001;
413 goto icmd_iconst_tail;
415 if ((iptr[0].val.i == 0x00000002) ||
416 (iptr[0].val.i == 0x00000004) ||
417 (iptr[0].val.i == 0x00000008) ||
418 (iptr[0].val.i == 0x00000010) ||
419 (iptr[0].val.i == 0x00000020) ||
420 (iptr[0].val.i == 0x00000040) ||
421 (iptr[0].val.i == 0x00000080) ||
422 (iptr[0].val.i == 0x00000100) ||
423 (iptr[0].val.i == 0x00000200) ||
424 (iptr[0].val.i == 0x00000400) ||
425 (iptr[0].val.i == 0x00000800) ||
426 (iptr[0].val.i == 0x00001000) ||
427 (iptr[0].val.i == 0x00002000) ||
428 (iptr[0].val.i == 0x00004000) ||
429 (iptr[0].val.i == 0x00008000) ||
430 (iptr[0].val.i == 0x00010000) ||
431 (iptr[0].val.i == 0x00020000) ||
432 (iptr[0].val.i == 0x00040000) ||
433 (iptr[0].val.i == 0x00080000) ||
434 (iptr[0].val.i == 0x00100000) ||
435 (iptr[0].val.i == 0x00200000) ||
436 (iptr[0].val.i == 0x00400000) ||
437 (iptr[0].val.i == 0x00800000) ||
438 (iptr[0].val.i == 0x01000000) ||
439 (iptr[0].val.i == 0x02000000) ||
440 (iptr[0].val.i == 0x04000000) ||
441 (iptr[0].val.i == 0x08000000) ||
442 (iptr[0].val.i == 0x10000000) ||
443 (iptr[0].val.i == 0x20000000) ||
444 (iptr[0].val.i == 0x40000000) ||
445 (iptr[0].val.i == 0x80000000)) {
446 iptr[0].opc = ICMD_IREMPOW2;
448 goto icmd_iconst_tail;
453 iptr[0].opc = ICMD_IANDCONST;
454 goto icmd_iconst_tail;
456 iptr[0].opc = ICMD_IORCONST;
457 goto icmd_iconst_tail;
459 iptr[0].opc = ICMD_IXORCONST;
460 goto icmd_iconst_tail;
462 iptr[0].opc = ICMD_ISHLCONST;
463 goto icmd_iconst_tail;
465 iptr[0].opc = ICMD_ISHRCONST;
466 goto icmd_iconst_tail;
468 iptr[0].opc = ICMD_IUSHRCONST;
469 goto icmd_iconst_tail;
471 iptr[0].opc = ICMD_IFEQ;
473 iptr[0].op1 = iptr[1].op1;
474 iptr[1].opc = ICMD_NOP;
476 tbptr = block + block_index[iptr->op1];
477 MARKREACHED(tbptr, copy);
478 COUNT(count_pcmd_bra);
481 iptr[0].opc = ICMD_IFLT;
482 goto icmd_if_icmp_tail;
484 iptr[0].opc = ICMD_IFLE;
485 goto icmd_if_icmp_tail;
487 iptr[0].opc = ICMD_IFNE;
488 goto icmd_if_icmp_tail;
490 iptr[0].opc = ICMD_IFGT;
491 goto icmd_if_icmp_tail;
493 iptr[0].opc = ICMD_IFGE;
494 goto icmd_if_icmp_tail;
503 COUNT(count_pcmd_load);
505 switch (iptr[1].opc) {
507 iptr[0].opc = ICMD_LADDCONST;
509 iptr[1].opc = ICMD_NOP;
510 OP1_1(TYPE_LNG,TYPE_LNG);
511 COUNT(count_pcmd_op);
514 iptr[0].opc = ICMD_LSUBCONST;
515 goto icmd_lconst_tail;
517 iptr[0].opc = ICMD_LMULCONST;
518 goto icmd_lconst_tail;
520 if (iptr[0].val.l == 0x00000002)
522 else if (iptr[0].val.l == 0x00000004)
524 else if (iptr[0].val.l == 0x00000008)
526 else if (iptr[0].val.l == 0x00000010)
528 else if (iptr[0].val.l == 0x00000020)
530 else if (iptr[0].val.l == 0x00000040)
532 else if (iptr[0].val.l == 0x00000080)
534 else if (iptr[0].val.l == 0x00000100)
536 else if (iptr[0].val.l == 0x00000200)
538 else if (iptr[0].val.l == 0x00000400)
540 else if (iptr[0].val.l == 0x00000800)
542 else if (iptr[0].val.l == 0x00001000)
544 else if (iptr[0].val.l == 0x00002000)
546 else if (iptr[0].val.l == 0x00004000)
548 else if (iptr[0].val.l == 0x00008000)
550 else if (iptr[0].val.l == 0x00010000)
552 else if (iptr[0].val.l == 0x00020000)
554 else if (iptr[0].val.l == 0x00040000)
556 else if (iptr[0].val.l == 0x00080000)
558 else if (iptr[0].val.l == 0x00100000)
560 else if (iptr[0].val.l == 0x00200000)
562 else if (iptr[0].val.l == 0x00400000)
564 else if (iptr[0].val.l == 0x00800000)
566 else if (iptr[0].val.l == 0x01000000)
568 else if (iptr[0].val.l == 0x02000000)
570 else if (iptr[0].val.l == 0x04000000)
572 else if (iptr[0].val.l == 0x08000000)
574 else if (iptr[0].val.l == 0x10000000)
576 else if (iptr[0].val.l == 0x20000000)
578 else if (iptr[0].val.l == 0x40000000)
580 else if (iptr[0].val.l == 0x80000000)
586 iptr[0].opc = ICMD_LDIVPOW2;
587 goto icmd_lconst_tail;
589 if (iptr[0].val.l == 0x10001) {
590 iptr[0].opc = ICMD_LREM0X10001;
591 goto icmd_lconst_tail;
593 if ((iptr[0].val.l == 0x00000002) ||
594 (iptr[0].val.l == 0x00000004) ||
595 (iptr[0].val.l == 0x00000008) ||
596 (iptr[0].val.l == 0x00000010) ||
597 (iptr[0].val.l == 0x00000020) ||
598 (iptr[0].val.l == 0x00000040) ||
599 (iptr[0].val.l == 0x00000080) ||
600 (iptr[0].val.l == 0x00000100) ||
601 (iptr[0].val.l == 0x00000200) ||
602 (iptr[0].val.l == 0x00000400) ||
603 (iptr[0].val.l == 0x00000800) ||
604 (iptr[0].val.l == 0x00001000) ||
605 (iptr[0].val.l == 0x00002000) ||
606 (iptr[0].val.l == 0x00004000) ||
607 (iptr[0].val.l == 0x00008000) ||
608 (iptr[0].val.l == 0x00010000) ||
609 (iptr[0].val.l == 0x00020000) ||
610 (iptr[0].val.l == 0x00040000) ||
611 (iptr[0].val.l == 0x00080000) ||
612 (iptr[0].val.l == 0x00100000) ||
613 (iptr[0].val.l == 0x00200000) ||
614 (iptr[0].val.l == 0x00400000) ||
615 (iptr[0].val.l == 0x00800000) ||
616 (iptr[0].val.l == 0x01000000) ||
617 (iptr[0].val.l == 0x02000000) ||
618 (iptr[0].val.l == 0x04000000) ||
619 (iptr[0].val.l == 0x08000000) ||
620 (iptr[0].val.l == 0x10000000) ||
621 (iptr[0].val.l == 0x20000000) ||
622 (iptr[0].val.l == 0x40000000) ||
623 (iptr[0].val.l == 0x80000000)) {
624 iptr[0].opc = ICMD_LREMPOW2;
626 goto icmd_lconst_tail;
631 iptr[0].opc = ICMD_LANDCONST;
632 goto icmd_lconst_tail;
634 iptr[0].opc = ICMD_LORCONST;
635 goto icmd_lconst_tail;
637 iptr[0].opc = ICMD_LXORCONST;
638 goto icmd_lconst_tail;
640 iptr[0].opc = ICMD_LSHLCONST;
641 goto icmd_lconst_tail;
643 iptr[0].opc = ICMD_LSHRCONST;
644 goto icmd_lconst_tail;
646 iptr[0].opc = ICMD_LUSHRCONST;
647 goto icmd_lconst_tail;
649 if ((len > 1) && (iptr[2].val.i == 0)) {
650 switch (iptr[2].opc) {
652 iptr[0].opc = ICMD_IF_LEQ;
653 icmd_lconst_lcmp_tail:
654 iptr[0].op1 = iptr[2].op1;
655 iptr[1].opc = ICMD_NOP;
656 iptr[2].opc = ICMD_NOP;
658 tbptr = block + block_index[iptr->op1];
659 MARKREACHED(tbptr, copy);
660 COUNT(count_pcmd_bra);
661 COUNT(count_pcmd_op);
664 iptr[0].opc = ICMD_IF_LNE;
665 goto icmd_lconst_lcmp_tail;
667 iptr[0].opc = ICMD_IF_LLT;
668 goto icmd_lconst_lcmp_tail;
670 iptr[0].opc = ICMD_IF_LGT;
671 goto icmd_lconst_lcmp_tail;
673 iptr[0].opc = ICMD_IF_LLE;
674 goto icmd_lconst_lcmp_tail;
676 iptr[0].opc = ICMD_IF_LGE;
677 goto icmd_lconst_lcmp_tail;
680 } /* switch (iptr[2].opc) */
681 } /* if (iptr[2].val.i == 0) */
693 COUNT(count_pcmd_load);
697 COUNT(count_pcmd_load);
701 COUNT(count_pcmd_load);
705 /* pop 0 push 1 load */
712 COUNT(count_load_instruction);
713 i = opcode-ICMD_ILOAD;
714 locals[iptr->op1][i].type = i;
715 LOAD(i, LOCALVAR, iptr->op1);
725 COUNT(count_check_null);
726 COUNT(count_check_bound);
727 COUNT(count_pcmd_mem);
728 OP2IAT_1(opcode-ICMD_IALOAD);
734 COUNT(count_check_null);
735 COUNT(count_check_bound);
736 COUNT(count_pcmd_mem);
740 /* pop 0 push 0 iinc */
746 count_store_depth[10]++;
748 count_store_depth[i]++;
753 if ((copy->varkind == LOCALVAR) &&
754 (copy->varnum == curstack->varnum)) {
755 copy->varkind = TEMPVAR;
764 /* pop 1 push 0 store */
771 i = opcode-ICMD_ISTORE;
772 locals[iptr->op1][i].type = i;
777 count_store_length[20]++;
779 count_store_length[i]++;
782 count_store_depth[10]++;
784 count_store_depth[i]++;
786 copy = curstack->prev;
789 if ((copy->varkind == LOCALVAR) &&
790 (copy->varnum == curstack->varnum)) {
791 copy->varkind = TEMPVAR;
797 if ((new - curstack) == 1) {
798 curstack->varkind = LOCALVAR;
799 curstack->varnum = iptr->op1;
801 STORE(opcode-ICMD_ISTORE);
811 COUNT(count_check_null);
812 COUNT(count_check_bound);
813 COUNT(count_pcmd_mem);
814 OP3TIA_0(opcode-ICMD_IASTORE);
819 COUNT(count_check_null);
820 COUNT(count_check_bound);
821 COUNT(count_pcmd_mem);
836 COUNT(count_pcmd_return);
837 OP1_0(opcode-ICMD_IRETURN);
838 superblockend = true;
842 COUNT(count_check_null);
846 superblockend = true;
850 COUNT(count_pcmd_mem);
854 /* pop 1 push 0 branch */
858 COUNT(count_pcmd_bra);
860 tbptr = block + block_index[iptr->op1];
861 MARKREACHED(tbptr, copy);
870 COUNT(count_pcmd_bra);
871 #ifdef CONDITIONAL_LOADCONST
873 tbptr = block + b_index;
874 if ((b_count >= 3) &&
875 ((b_index + 2) == block_index[iptr[0].op1]) &&
876 (tbptr[1].pre_count == 1) &&
877 (iptr[1].opc == ICMD_ICONST) &&
878 (iptr[2].opc == ICMD_GOTO) &&
879 ((b_index + 3) == block_index[iptr[2].op1]) &&
880 (tbptr[2].pre_count == 1) &&
881 (iptr[3].opc == ICMD_ICONST)) {
882 OP1_1(TYPE_INT, TYPE_INT);
883 switch (iptr[0].opc) {
885 iptr[0].opc = ICMD_IFNE_ICONST;
888 iptr[0].opc = ICMD_IFEQ_ICONST;
891 iptr[0].opc = ICMD_IFGE_ICONST;
894 iptr[0].opc = ICMD_IFLT_ICONST;
897 iptr[0].opc = ICMD_IFLE_ICONST;
900 iptr[0].opc = ICMD_IFGT_ICONST;
903 iptr[0].val.i = iptr[1].val.i;
904 iptr[1].opc = ICMD_ELSE_ICONST;
905 iptr[1].val.i = iptr[3].val.i;
906 iptr[2].opc = ICMD_NOP;
907 iptr[3].opc = ICMD_NOP;
908 tbptr[1].flags = BBDELETED;
909 tbptr[2].flags = BBDELETED;
911 if (tbptr[3].pre_count == 2) {
912 tbptr[3].flags = BBDELETED;
913 len += tbptr[4].ipc - tbptr[3].ipc;
914 tbptr[3].ipc = tbptr[4].ipc;
917 tbptr[1].ipc = tbptr[3].ipc;
918 tbptr[2].ipc = tbptr[3].ipc;
919 bptr[1].ipc = tbptr[3].ipc;
926 tbptr = block + block_index[iptr->op1];
927 MARKREACHED(tbptr, copy);
930 /* pop 0 push 0 branch */
933 COUNT(count_pcmd_bra);
934 tbptr = block + block_index[iptr->op1];
935 MARKREACHED(tbptr, copy);
937 superblockend = true;
940 /* pop 1 push 0 table branch */
942 case ICMD_TABLESWITCH:
943 COUNT(count_pcmd_table);
946 tbptr = block + block_index[*s4ptr++]; /* default */
947 MARKREACHED(tbptr, copy);
948 i = *s4ptr++; /* low */
949 i = *s4ptr++ - i + 1; /* high */
951 tbptr = block + block_index[*s4ptr++];
952 MARKREACHED(tbptr, copy);
955 superblockend = true;
958 /* pop 1 push 0 table branch */
960 case ICMD_LOOKUPSWITCH:
961 COUNT(count_pcmd_table);
964 tbptr = block + block_index[*s4ptr++]; /* default */
965 MARKREACHED(tbptr, copy);
966 i = *s4ptr++; /* count */
968 tbptr = block + block_index[s4ptr[1]];
969 MARKREACHED(tbptr, copy);
973 superblockend = true;
976 case ICMD_NULLCHECKPOP:
977 case ICMD_MONITORENTER:
978 COUNT(count_check_null);
979 case ICMD_MONITOREXIT:
983 /* pop 2 push 0 branch */
991 COUNT(count_pcmd_bra);
993 tbptr = block + block_index[iptr->op1];
994 MARKREACHED(tbptr, copy);
999 COUNT(count_pcmd_bra);
1001 tbptr = block + block_index[iptr->op1];
1002 MARKREACHED(tbptr, copy);
1008 COUNT(count_check_null);
1009 COUNT(count_pcmd_mem);
1010 OPTT2_0(iptr->op1,TYPE_ADR);
1014 if (! IS_2_WORD_TYPE(curstack->type)) {
1015 OP1_0ANY; /* second pop */
1018 iptr->opc = ICMD_POP;
1022 /* pop 0 push 1 dup */
1025 COUNT(count_dup_instruction);
1030 if (IS_2_WORD_TYPE(curstack->type)) {
1031 iptr->opc = ICMD_DUP;
1036 NEWSTACK(copy[-1].type, copy[-1].varkind,
1038 NEWSTACK(copy[ 0].type, copy[ 0].varkind,
1045 /* pop 2 push 3 dup */
1052 if (IS_2_WORD_TYPE(curstack->type)) {
1053 iptr->opc = ICMD_DUP_X1;
1061 /* pop 3 push 4 dup */
1064 if (IS_2_WORD_TYPE(curstack[-1].type)) {
1065 iptr->opc = ICMD_DUP_X1;
1074 if (IS_2_WORD_TYPE(curstack->type)) {
1075 if (IS_2_WORD_TYPE(curstack[-1].type)) {
1076 iptr->opc = ICMD_DUP_X1;
1080 iptr->opc = ICMD_DUP_X2;
1085 if (IS_2_WORD_TYPE(curstack[-2].type)) {
1086 iptr->opc = ICMD_DUP2_X1;
1094 /* pop 2 push 2 swap */
1103 if (!(SUPPORT_DIVISION)) {
1104 iptr[0].opc = ICMD_BUILTIN2;
1105 iptr[0].op1 = TYPE_INT;
1106 iptr[0].val.a = (functionptr) new_builtin_idiv;
1107 isleafmethod = false;
1112 if (!(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV)) {
1113 iptr[0].opc = ICMD_BUILTIN2;
1114 iptr[0].op1 = TYPE_LNG;
1115 iptr[0].val.a = (functionptr) new_builtin_ldiv;
1116 isleafmethod = false;
1121 if (!(SUPPORT_DIVISION)) {
1122 iptr[0].opc = ICMD_BUILTIN2;
1123 iptr[0].op1 = TYPE_INT;
1124 iptr[0].val.a = (functionptr) new_builtin_irem;
1125 isleafmethod = false;
1130 if (!(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV)) {
1131 iptr[0].opc = ICMD_BUILTIN2;
1132 iptr[0].op1 = TYPE_LNG;
1133 iptr[0].val.a = (functionptr) new_builtin_lrem;
1134 isleafmethod = false;
1148 COUNT(count_pcmd_op);
1159 COUNT(count_pcmd_op);
1166 COUNT(count_pcmd_op);
1175 COUNT(count_pcmd_op);
1184 COUNT(count_pcmd_op);
1189 COUNT(count_pcmd_op);
1190 if ((len > 0) && (iptr[1].val.i == 0)) {
1191 switch (iptr[1].opc) {
1193 iptr[0].opc = ICMD_IF_LCMPEQ;
1195 iptr[0].op1 = iptr[1].op1;
1196 iptr[1].opc = ICMD_NOP;
1198 tbptr = block + block_index[iptr->op1];
1199 MARKREACHED(tbptr, copy);
1200 COUNT(count_pcmd_bra);
1203 iptr[0].opc = ICMD_IF_LCMPNE;
1204 goto icmd_lcmp_if_tail;
1206 iptr[0].opc = ICMD_IF_LCMPLT;
1207 goto icmd_lcmp_if_tail;
1209 iptr[0].opc = ICMD_IF_LCMPGT;
1210 goto icmd_lcmp_if_tail;
1212 iptr[0].opc = ICMD_IF_LCMPLE;
1213 goto icmd_lcmp_if_tail;
1215 iptr[0].opc = ICMD_IF_LCMPGE;
1216 goto icmd_lcmp_if_tail;
1218 OPTT2_1(TYPE_LNG, TYPE_INT);
1222 OPTT2_1(TYPE_LNG, TYPE_INT);
1226 COUNT(count_pcmd_op);
1227 OPTT2_1(TYPE_FLT, TYPE_INT);
1231 COUNT(count_pcmd_op);
1232 OPTT2_1(TYPE_DBL, TYPE_INT);
1240 case ICMD_INT2SHORT:
1241 COUNT(count_pcmd_op);
1242 OP1_1(TYPE_INT, TYPE_INT);
1245 COUNT(count_pcmd_op);
1246 OP1_1(TYPE_LNG, TYPE_LNG);
1249 COUNT(count_pcmd_op);
1250 OP1_1(TYPE_FLT, TYPE_FLT);
1253 COUNT(count_pcmd_op);
1254 OP1_1(TYPE_DBL, TYPE_DBL);
1258 COUNT(count_pcmd_op);
1259 OP1_1(TYPE_INT, TYPE_LNG);
1262 COUNT(count_pcmd_op);
1263 OP1_1(TYPE_INT, TYPE_FLT);
1266 COUNT(count_pcmd_op);
1267 OP1_1(TYPE_INT, TYPE_DBL);
1270 COUNT(count_pcmd_op);
1271 OP1_1(TYPE_LNG, TYPE_INT);
1274 COUNT(count_pcmd_op);
1275 OP1_1(TYPE_LNG, TYPE_FLT);
1278 COUNT(count_pcmd_op);
1279 OP1_1(TYPE_LNG, TYPE_DBL);
1282 COUNT(count_pcmd_op);
1283 OP1_1(TYPE_FLT, TYPE_INT);
1286 COUNT(count_pcmd_op);
1287 OP1_1(TYPE_FLT, TYPE_LNG);
1290 COUNT(count_pcmd_op);
1291 OP1_1(TYPE_FLT, TYPE_DBL);
1294 COUNT(count_pcmd_op);
1295 OP1_1(TYPE_DBL, TYPE_INT);
1298 COUNT(count_pcmd_op);
1299 OP1_1(TYPE_DBL, TYPE_LNG);
1302 COUNT(count_pcmd_op);
1303 OP1_1(TYPE_DBL, TYPE_FLT);
1306 case ICMD_CHECKCAST:
1307 OP1_1(TYPE_ADR, TYPE_ADR);
1310 case ICMD_ARRAYLENGTH:
1311 case ICMD_INSTANCEOF:
1312 OP1_1(TYPE_ADR, TYPE_INT);
1316 case ICMD_ANEWARRAY:
1317 OP1_1(TYPE_INT, TYPE_ADR);
1321 COUNT(count_check_null);
1322 COUNT(count_pcmd_mem);
1323 OP1_1(TYPE_ADR, iptr->op1);
1328 case ICMD_GETSTATIC:
1329 COUNT(count_pcmd_mem);
1339 tbptr = block + block_index[iptr->op1];
1340 tbptr->type=BBTYPE_SBR;
1341 MARKREACHED(tbptr, copy);
1345 /* pop many push any */
1347 case ICMD_INVOKEVIRTUAL:
1348 case ICMD_INVOKESPECIAL:
1349 case ICMD_INVOKEINTERFACE:
1350 case ICMD_INVOKESTATIC:
1351 COUNT(count_pcmd_met);
1353 methodinfo *m = iptr->val.a;
1354 if (m->flags & ACC_STATIC)
1355 {COUNT(count_check_null);}
1357 if (i > arguments_num)
1361 if (! (copy->flags & SAVEDVAR)) {
1362 copy->varkind = ARGVAR;
1368 copy->flags |= SAVEDVAR;
1373 if (m->returntype != TYPE_VOID) {
1374 OP0_1(m->returntype);
1380 if (! (curstack->flags & SAVEDVAR)) {
1381 curstack->varkind = ARGVAR;
1382 curstack->varnum = 2;
1387 if (! (curstack->flags & SAVEDVAR)) {
1388 curstack->varkind = ARGVAR;
1389 curstack->varnum = 1;
1393 if (! (curstack->flags & SAVEDVAR)) {
1394 curstack->varkind = ARGVAR;
1395 curstack->varnum = 0;
1400 copy->flags |= SAVEDVAR;
1403 if (iptr->op1 != TYPE_VOID)
1407 case ICMD_MULTIANEWARRAY:
1409 if ((i + intreg_argnum) > arguments_num)
1410 arguments_num = i + intreg_argnum;
1413 if (! (copy->flags & SAVEDVAR)) {
1414 copy->varkind = ARGVAR;
1415 copy->varnum = i + intreg_argnum;
1420 copy->flags |= SAVEDVAR;
1429 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1430 panic("Missing ICMD code during stack analysis");
1433 } /* while instructions */
1434 bptr->outstack = curstack;
1435 bptr->outdepth = stackdepth;
1439 superblockend = true;
1441 } /* while blocks */
1442 } while (repeat && ! deadcode);
1445 if (block_count > count_max_basic_blocks)
1446 count_max_basic_blocks = block_count;
1447 count_basic_blocks += block_count;
1448 if (block[block_count].ipc > count_max_javainstr)
1449 count_max_javainstr = block[block_count].ipc;
1450 count_javainstr += block[block_count].ipc;
1451 if (stack_count > count_upper_bound_new_stack)
1452 count_upper_bound_new_stack = stack_count;
1453 if ((new - stack) > count_max_new_stack)
1454 count_max_new_stack = (new - stack);
1456 b_count = block_count;
1458 while (--b_count >= 0) {
1459 if (bptr->flags > BBREACHED) {
1460 if (bptr->indepth >= 10)
1461 count_block_stack[10]++;
1463 count_block_stack[bptr->indepth]++;
1464 len = bptr[1].ipc - bptr[0].ipc;
1466 count_block_size_distribution[len - 1]++;
1468 count_block_size_distribution[10]++;
1470 count_block_size_distribution[11]++;
1472 count_block_size_distribution[12]++;
1474 count_block_size_distribution[13]++;
1476 count_block_size_distribution[14]++;
1478 count_block_size_distribution[15]++;
1480 count_block_size_distribution[16]++;
1482 count_block_size_distribution[17]++;
1488 count_analyse_iterations[0]++;
1489 else if (loops == 2)
1490 count_analyse_iterations[1]++;
1491 else if (loops == 3)
1492 count_analyse_iterations[2]++;
1493 else if (loops == 4)
1494 count_analyse_iterations[3]++;
1496 count_analyse_iterations[4]++;
1498 if (block_count <= 5)
1499 count_method_bb_distribution[0]++;
1500 else if (block_count <= 10)
1501 count_method_bb_distribution[1]++;
1502 else if (block_count <= 15)
1503 count_method_bb_distribution[2]++;
1504 else if (block_count <= 20)
1505 count_method_bb_distribution[3]++;
1506 else if (block_count <= 30)
1507 count_method_bb_distribution[4]++;
1508 else if (block_count <= 40)
1509 count_method_bb_distribution[5]++;
1510 else if (block_count <= 50)
1511 count_method_bb_distribution[6]++;
1512 else if (block_count <= 75)
1513 count_method_bb_distribution[7]++;
1515 count_method_bb_distribution[8]++;
1520 static void print_stack(stackptr s) {
1536 if (s->flags & SAVEDVAR)
1537 switch (s->varkind) {
1539 if (s->flags & INMEMORY)
1540 printf(" m%02d", s->regoff);
1542 printf(" r%02d", s->regoff);
1545 printf(" s%02d", s->varnum);
1548 printf(" l%02d", s->varnum);
1551 printf(" a%02d", s->varnum);
1554 printf(" !%02d", j);
1557 switch (s->varkind) {
1559 if (s->flags & INMEMORY)
1560 printf(" M%02d", s->regoff);
1562 printf(" R%02d", s->regoff);
1565 printf(" S%02d", s->varnum);
1568 printf(" L%02d", s->varnum);
1571 printf(" A%02d", s->varnum);
1574 printf(" ?%02d", j);
1581 static void print_reg(stackptr s) {
1583 if (s->flags & SAVEDVAR)
1584 switch (s->varkind) {
1586 if (s->flags & INMEMORY)
1587 printf(" tm%02d", s->regoff);
1589 printf(" tr%02d", s->regoff);
1592 printf(" s %02d", s->varnum);
1595 printf(" l %02d", s->varnum);
1598 printf(" a %02d", s->varnum);
1601 printf(" ! %02d", s->varnum);
1604 switch (s->varkind) {
1606 if (s->flags & INMEMORY)
1607 printf(" Tm%02d", s->regoff);
1609 printf(" Tr%02d", s->regoff);
1612 printf(" S %02d", s->varnum);
1615 printf(" L %02d", s->varnum);
1618 printf(" A %02d", s->varnum);
1621 printf(" ? %02d", s->varnum);
1630 static char *builtin_name(functionptr bptr)
1632 builtin_descriptor *bdesc = builtin_desc;
1633 while ((bdesc->bptr != NULL) && (bdesc->bptr != bptr))
1639 static void show_icmd_method()
1646 unicode_fprint(stdout, class->name);
1648 unicode_fprint(stdout, method->name);
1650 unicode_fprint(stdout, method->descriptor);
1651 printf ("\n\nMax locals: %d\n", (int) maxlocals);
1652 printf ("Max stack: %d\n", (int) maxstack);
1654 printf ("Exceptions:\n");
1655 for (i = 0; i < exceptiontablelength; i++) {
1656 printf(" L%03d ... ", block_index[extable[i].startpc]);
1657 printf("L%03d = ", block_index[extable[i].endpc]);
1658 printf("L%03d\n", block_index[extable[i].handlerpc]);
1661 printf ("Local Table:\n");
1662 for (i = 0; i < maxlocals; i++) {
1663 printf(" %3d: ", i);
1664 for (j = TYPE_INT; j <= TYPE_ADR; j++)
1665 if (locals[i][j].type >= 0) {
1666 printf(" (%d) ", j);
1667 if (locals[i][j].flags)
1671 printf("%2d", locals[i][j].regoff);
1677 printf ("Interface Table:\n");
1678 for (i = 0; i < maxstack; i++) {
1679 if ((interfaces[i][0].type >= 0) || (interfaces[i][1].type >= 0) ||
1680 (interfaces[i][2].type >= 0) || (interfaces[i][3].type >= 0) ||
1681 (interfaces[i][4].type >= 0)) {
1682 printf(" %3d: ", i);
1683 for (j = TYPE_INT; j <= TYPE_ADR; j++)
1684 if (interfaces[i][j].type >= 0) {
1685 printf(" (%d) ", j);
1686 if (interfaces[i][j].flags & SAVEDVAR)
1690 if (interfaces[i][j].flags & INMEMORY)
1694 printf("%2d", interfaces[i][j].regoff);
1701 if (showdisassemble) {
1702 s4ptr = (s4 *) (method->mcode + dseglen);
1703 for (i = 0; i < block[0].mpc; i += 4, s4ptr++) {
1704 disasscmd (*s4ptr, i);
1709 for (b = 0; b < block_count; b++)
1710 if (block[b].flags != BBDELETED) {
1711 deadcode = block[b].flags <= BBREACHED;
1714 for (j = maxstack; j > 0; j--)
1717 print_stack(block[b].instack);
1718 printf("] L%03d(%d):\n", b, block[b].pre_count);
1719 for (i = block[b].ipc; i < block[b + 1].ipc; i++) {
1722 for (j = maxstack; j > 0; j--)
1726 print_stack(instr[i].dst);
1727 printf("] %4d %s", i, icmd_names[instr[i].opc]);
1728 switch ((int) instr[i].opc) {
1729 case ICMD_IADDCONST:
1730 case ICMD_ISUBCONST:
1731 case ICMD_IMULCONST:
1734 case ICMD_IREM0X10001:
1735 case ICMD_IANDCONST:
1737 case ICMD_IXORCONST:
1738 case ICMD_ISHLCONST:
1739 case ICMD_ISHRCONST:
1740 case ICMD_IUSHRCONST:
1742 case ICMD_ELSE_ICONST:
1743 case ICMD_IFEQ_ICONST:
1744 case ICMD_IFNE_ICONST:
1745 case ICMD_IFLT_ICONST:
1746 case ICMD_IFGE_ICONST:
1747 case ICMD_IFGT_ICONST:
1748 case ICMD_IFLE_ICONST:
1749 printf(" %d", instr[i].val.i);
1751 case ICMD_LADDCONST:
1752 case ICMD_LSUBCONST:
1753 case ICMD_LMULCONST:
1756 case ICMD_LANDCONST:
1758 case ICMD_LXORCONST:
1759 case ICMD_LSHLCONST:
1760 case ICMD_LSHRCONST:
1761 case ICMD_LUSHRCONST:
1763 printf(" %ld", instr[i].val.l);
1766 printf(" %f", instr[i].val.f);
1769 printf(" %f", instr[i].val.d);
1772 printf(" %p", instr[i].val.a);
1776 printf(" %d,", ((fieldinfo *) instr[i].val.a)->offset);
1777 case ICMD_PUTSTATIC:
1778 case ICMD_GETSTATIC:
1780 unicode_fprint(stdout,
1781 ((fieldinfo *) instr[i].val.a)->name);
1784 printf(" %d + %d", instr[i].op1, instr[i].val.i);
1797 printf(" %d", instr[i].op1);
1801 unicode_fprint(stdout,
1802 ((classinfo *) instr[i].val.a)->name);
1805 switch (instr[i].op1) {
1832 case ICMD_ANEWARRAY:
1835 unicode_fprint(stdout,
1836 ((classinfo *) instr[i].val.a)->name);
1839 case ICMD_CHECKCAST:
1840 case ICMD_INSTANCEOF:
1843 unicode_fprint(stdout,
1844 ((classinfo *) instr[i].val.a)->name);
1850 printf(" %s", builtin_name((functionptr) instr[i].val.a));
1852 case ICMD_INVOKEVIRTUAL:
1853 case ICMD_INVOKESPECIAL:
1854 case ICMD_INVOKESTATIC:
1855 case ICMD_INVOKEINTERFACE:
1857 unicode_fprint(stdout,
1858 ((methodinfo *) instr[i].val.a)->class->name);
1860 unicode_fprint(stdout,
1861 ((methodinfo *) instr[i].val.a)->name);
1875 printf("(%d) L%03d", instr[i].val.i, block_index[instr[i].op1]);
1880 case ICMD_IFNONNULL:
1881 case ICMD_IF_ICMPEQ:
1882 case ICMD_IF_ICMPNE:
1883 case ICMD_IF_ICMPLT:
1884 case ICMD_IF_ICMPGE:
1885 case ICMD_IF_ICMPGT:
1886 case ICMD_IF_ICMPLE:
1887 case ICMD_IF_LCMPEQ:
1888 case ICMD_IF_LCMPNE:
1889 case ICMD_IF_LCMPLT:
1890 case ICMD_IF_LCMPGE:
1891 case ICMD_IF_LCMPGT:
1892 case ICMD_IF_LCMPLE:
1893 case ICMD_IF_ACMPEQ:
1894 case ICMD_IF_ACMPNE:
1895 printf(" L%03d", block_index[instr[i].op1]);
1897 case ICMD_TABLESWITCH:
1898 s4ptr = instr[i].val.a;
1899 printf(" L%03d;", block_index[*s4ptr++]); /* default */
1900 j = *s4ptr++; /* low */
1901 j = *s4ptr++ - j; /* high */
1903 printf(" L%03d", block_index[*s4ptr++]);
1907 case ICMD_LOOKUPSWITCH:
1908 s4ptr = instr[i].val.a;
1909 printf(" L%d", block_index[*s4ptr++]); /* default */
1910 j = *s4ptr++; /* count */
1912 printf(" L%03d", block_index[s4ptr[1]]);
1920 if (showdisassemble && (!deadcode)) {
1923 s4ptr = (s4 *) (method->mcode + dseglen + i);
1924 for (; i < block[b + 1].mpc; i += 4, s4ptr++) {
1925 disasscmd (*s4ptr, i);