1 /* jit/stack.c *****************************************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 Parser for JavaVM to intermediate code translation
9 Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
11 Last Change: 1997/11/18
13 *******************************************************************************/
15 #define CONDITIONAL_LOADCONST
18 #define COUNT(cnt) cnt++
23 #define STACKRESET {curstack=0;stackdepth=0;}
25 #define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");}
26 #define CURKIND curstack->varkind
27 #define CURTYPE curstack->type
29 #define NEWSTACK(s,v,n) {new->prev=curstack;new->type=s;new->flags=0;\
30 new->varkind=v;new->varnum=n;curstack=new;new++;}
31 #define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
32 #define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
33 #define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
35 #define SETDST {iptr->dst=curstack;}
36 #define POP(s) {if(s!=curstack->type){TYPEPANIC;}\
37 if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
38 curstack=curstack->prev;}
39 #define POPANY {if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
40 curstack=curstack->prev;}
41 #define COPY(s,d) {(d)->flags=0;(d)->type=(s)->type;\
42 (d)->varkind=(s)->varkind;(d)->varnum=(s)->varnum;}
44 #define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
45 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
46 #define STORE(s) {POP(s);SETDST;stackdepth--;}
47 #define OP1_0(s) {POP(s);SETDST;stackdepth--;}
48 #define OP1_0ANY {POPANY;SETDST;stackdepth--;}
49 #define OP0_1(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
50 #define OP1_1(s,d) {POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
51 #define OP2_0(s) {POP(s);POP(s);SETDST;stackdepth-=2;}
52 #define OPTT2_0(t,b){POP(t);POP(b);SETDST;stackdepth-=2;}
53 #define OP2_1(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
54 #define OP2IAT_1(s) {POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
56 #define OP2IT_1(s) {POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
58 #define OPTT2_1(s,d){POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
59 #define OP2_2(s) {POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
60 NEWSTACKn(s,stackdepth-1);SETDST;}
61 #define OP3TIA_0(s) {POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
62 #define OP3_0(s) {POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
63 #define POPMANY(i) {stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
64 #define DUP {NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST;\
66 #define SWAP {COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
67 new[0].prev=curstack;new[1].prev=new;\
68 curstack=new+1;new+=2;SETDST;}
69 #define DUP_X1 {COPY(curstack,new);COPY(curstack,new+2);POPANY;\
70 COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
71 new[1].prev=new;new[2].prev=new+1;\
72 curstack=new+2;new+=3;SETDST;stackdepth++;}
73 #define DUP2_X1 {COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
74 COPY(curstack,new);COPY(curstack,new+3);POPANY;\
75 COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
76 new[1].prev=new;new[2].prev=new+1;\
77 new[3].prev=new+2;new[4].prev=new+3;\
78 curstack=new+4;new+=5;SETDST;stackdepth+=2;}
79 #define DUP_X2 {COPY(curstack,new);COPY(curstack,new+3);POPANY;\
80 COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
81 new[0].prev=curstack;new[1].prev=new;\
82 new[2].prev=new+1;new[3].prev=new+2;\
83 curstack=new+3;new+=4;SETDST;stackdepth++;}
84 #define DUP2_X2 {COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
85 COPY(curstack,new);COPY(curstack,new+4);POPANY;\
86 COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
87 new[0].prev=curstack;new[1].prev=new;\
88 new[2].prev=new+1;new[3].prev=new+2;\
89 new[4].prev=new+3;new[5].prev=new+4;\
90 curstack=new+5;new+=6;SETDST;stackdepth+=2;}
92 #define COPYCURSTACK(copy) {\
105 copy->varkind=STACKVAR;\
121 if((copy->varkind==STACKVAR)&&(copy->varnum>i))\
122 copy->varkind=TEMPVAR;\
124 copy->varkind=STACKVAR;\
127 interfaces[i][copy->type].type = copy->type;\
128 interfaces[i][copy->type].flags |= copy->flags;\
129 i--;copy=copy->prev;\
134 interfaces[i][copy->type].type = copy->type;\
135 if(copy->varkind==STACKVAR){\
136 if (copy->flags & SAVEDVAR)\
137 interfaces[i][copy->type].flags |= SAVEDVAR;\
139 i--;copy=copy->prev;\
144 #define MARKREACHED(b,c) {\
146 {COPYCURSTACK(c);b->flags=0;b->instack=c;b->indepth=stackdepth;}\
147 else {stackptr s=curstack;stackptr t=b->instack;\
148 if(b->indepth!=stackdepth)\
149 {show_icmd_method();panic("Stack depth mismatch");}\
150 while(s){if (s->type!=t->type)\
152 s=s->prev;t=t->prev;\
158 static void show_icmd_method();
160 static void analyse_stack()
162 int b_count, b_index;
164 stackptr curstack, new, copy;
165 int opcode, i, len, loops;
166 int superblockend, repeat, deadcode;
167 instruction *iptr = instr;
168 basicblock *bptr, *tbptr;
174 block[0].flags = BBREACHED;
175 block[0].instack = 0;
176 block[0].indepth = 0;
178 for (i = 0; i < exceptiontablelength; i++) {
179 bptr = &block[block_index[extable[i].handlerpc]];
180 bptr->flags = BBREACHED;
181 bptr->type = BBTYPE_EXH;
184 bptr->pre_count = 10000;
189 #ifdef CONDITIONAL_LOADCONST
190 b_count = block_count;
192 while (--b_count >= 0) {
193 if (bptr->icount != 0) {
194 iptr = bptr->iinstr + bptr->icount - 1;
227 block[block_index[iptr->op1]].pre_count++;
230 case ICMD_TABLESWITCH:
232 block[block_index[*s4ptr++]].pre_count++; /* default */
233 i = *s4ptr++; /* low */
234 i = *s4ptr++ - i + 1; /* high */
236 block[block_index[*s4ptr++]].pre_count++;
240 case ICMD_LOOKUPSWITCH:
242 block[block_index[*s4ptr++]].pre_count++; /* default */
243 i = *s4ptr++; /* count */
245 block[block_index[s4ptr[1]]].pre_count++;
261 b_count = block_count;
263 superblockend = true;
267 while (--b_count >= 0) {
268 if (bptr->flags == BBDELETED) {
271 else if (superblockend && (bptr->flags < BBREACHED))
273 else if (bptr->flags <= BBREACHED) {
275 stackdepth = bptr->indepth;
276 else if (bptr->flags < BBREACHED) {
278 bptr->instack = copy;
279 bptr->indepth = stackdepth;
281 else if (bptr->indepth != stackdepth) {
283 panic("Stack depth mismatch");
286 curstack = bptr->instack;
288 superblockend = false;
289 bptr->flags = BBFINISHED;
292 b_index = bptr - block;
300 case ICMD_CHECKASIZE:
302 case ICMD_IFEQ_ICONST:
303 case ICMD_IFNE_ICONST:
304 case ICMD_IFLT_ICONST:
305 case ICMD_IFGE_ICONST:
306 case ICMD_IFGT_ICONST:
307 case ICMD_IFLE_ICONST:
308 case ICMD_ELSE_ICONST:
313 locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
315 COUNT(count_pcmd_return);
317 superblockend = true;
320 /* pop 0 push 1 const */
323 COUNT(count_pcmd_load);
325 switch (iptr[1].opc) {
327 iptr[0].opc = ICMD_IADDCONST;
329 iptr[1].opc = ICMD_NOP;
330 OP1_1(TYPE_INT,TYPE_INT);
331 COUNT(count_pcmd_op);
334 iptr[0].opc = ICMD_ISUBCONST;
335 goto icmd_iconst_tail;
337 iptr[0].opc = ICMD_IMULCONST;
338 goto icmd_iconst_tail;
340 if (iptr[0].val.i == 0x00000002)
342 else if (iptr[0].val.i == 0x00000004)
344 else if (iptr[0].val.i == 0x00000008)
346 else if (iptr[0].val.i == 0x00000010)
348 else if (iptr[0].val.i == 0x00000020)
350 else if (iptr[0].val.i == 0x00000040)
352 else if (iptr[0].val.i == 0x00000080)
354 else if (iptr[0].val.i == 0x00000100)
356 else if (iptr[0].val.i == 0x00000200)
358 else if (iptr[0].val.i == 0x00000400)
360 else if (iptr[0].val.i == 0x00000800)
362 else if (iptr[0].val.i == 0x00001000)
364 else if (iptr[0].val.i == 0x00002000)
366 else if (iptr[0].val.i == 0x00004000)
368 else if (iptr[0].val.i == 0x00008000)
370 else if (iptr[0].val.i == 0x00010000)
372 else if (iptr[0].val.i == 0x00020000)
374 else if (iptr[0].val.i == 0x00040000)
376 else if (iptr[0].val.i == 0x00080000)
378 else if (iptr[0].val.i == 0x00100000)
380 else if (iptr[0].val.i == 0x00200000)
382 else if (iptr[0].val.i == 0x00400000)
384 else if (iptr[0].val.i == 0x00800000)
386 else if (iptr[0].val.i == 0x01000000)
388 else if (iptr[0].val.i == 0x02000000)
390 else if (iptr[0].val.i == 0x04000000)
392 else if (iptr[0].val.i == 0x08000000)
394 else if (iptr[0].val.i == 0x10000000)
396 else if (iptr[0].val.i == 0x20000000)
398 else if (iptr[0].val.i == 0x40000000)
400 else if (iptr[0].val.i == 0x80000000)
406 iptr[0].opc = ICMD_IDIVPOW2;
407 goto icmd_iconst_tail;
409 if (iptr[0].val.i == 0x10001) {
410 iptr[0].opc = ICMD_IREM0X10001;
411 goto icmd_iconst_tail;
413 if ((iptr[0].val.i == 0x00000002) ||
414 (iptr[0].val.i == 0x00000004) ||
415 (iptr[0].val.i == 0x00000008) ||
416 (iptr[0].val.i == 0x00000010) ||
417 (iptr[0].val.i == 0x00000020) ||
418 (iptr[0].val.i == 0x00000040) ||
419 (iptr[0].val.i == 0x00000080) ||
420 (iptr[0].val.i == 0x00000100) ||
421 (iptr[0].val.i == 0x00000200) ||
422 (iptr[0].val.i == 0x00000400) ||
423 (iptr[0].val.i == 0x00000800) ||
424 (iptr[0].val.i == 0x00001000) ||
425 (iptr[0].val.i == 0x00002000) ||
426 (iptr[0].val.i == 0x00004000) ||
427 (iptr[0].val.i == 0x00008000) ||
428 (iptr[0].val.i == 0x00010000) ||
429 (iptr[0].val.i == 0x00020000) ||
430 (iptr[0].val.i == 0x00040000) ||
431 (iptr[0].val.i == 0x00080000) ||
432 (iptr[0].val.i == 0x00100000) ||
433 (iptr[0].val.i == 0x00200000) ||
434 (iptr[0].val.i == 0x00400000) ||
435 (iptr[0].val.i == 0x00800000) ||
436 (iptr[0].val.i == 0x01000000) ||
437 (iptr[0].val.i == 0x02000000) ||
438 (iptr[0].val.i == 0x04000000) ||
439 (iptr[0].val.i == 0x08000000) ||
440 (iptr[0].val.i == 0x10000000) ||
441 (iptr[0].val.i == 0x20000000) ||
442 (iptr[0].val.i == 0x40000000) ||
443 (iptr[0].val.i == 0x80000000)) {
444 iptr[0].opc = ICMD_IREMPOW2;
446 goto icmd_iconst_tail;
451 iptr[0].opc = ICMD_IANDCONST;
452 goto icmd_iconst_tail;
454 iptr[0].opc = ICMD_IORCONST;
455 goto icmd_iconst_tail;
457 iptr[0].opc = ICMD_IXORCONST;
458 goto icmd_iconst_tail;
460 iptr[0].opc = ICMD_ISHLCONST;
461 goto icmd_iconst_tail;
463 iptr[0].opc = ICMD_ISHRCONST;
464 goto icmd_iconst_tail;
466 iptr[0].opc = ICMD_IUSHRCONST;
467 goto icmd_iconst_tail;
469 iptr[0].opc = ICMD_IFEQ;
471 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;
657 /* iptr[1].opc = ICMD_NOP;
658 iptr[2].opc = ICMD_NOP; */
660 tbptr = block + block_index[iptr->op1];
661 MARKREACHED(tbptr, copy);
662 COUNT(count_pcmd_bra);
663 COUNT(count_pcmd_op);
666 iptr[0].opc = ICMD_IF_LNE;
667 goto icmd_lconst_lcmp_tail;
669 iptr[0].opc = ICMD_IF_LLT;
670 goto icmd_lconst_lcmp_tail;
672 iptr[0].opc = ICMD_IF_LGT;
673 goto icmd_lconst_lcmp_tail;
675 iptr[0].opc = ICMD_IF_LLE;
676 goto icmd_lconst_lcmp_tail;
678 iptr[0].opc = ICMD_IF_LGE;
679 goto icmd_lconst_lcmp_tail;
682 } /* switch (iptr[2].opc) */
683 } /* if (iptr[2].val.i == 0) */
695 COUNT(count_pcmd_load);
699 COUNT(count_pcmd_load);
703 COUNT(count_pcmd_load);
707 /* pop 0 push 1 load */
714 COUNT(count_load_instruction);
715 i = opcode-ICMD_ILOAD;
716 locals[iptr->op1][i].type = i;
717 LOAD(i, LOCALVAR, iptr->op1);
727 COUNT(count_check_null);
728 COUNT(count_check_bound);
729 COUNT(count_pcmd_mem);
730 OP2IAT_1(opcode-ICMD_IALOAD);
736 COUNT(count_check_null);
737 COUNT(count_check_bound);
738 COUNT(count_pcmd_mem);
742 /* pop 0 push 0 iinc */
748 count_store_depth[10]++;
750 count_store_depth[i]++;
755 if ((copy->varkind == LOCALVAR) &&
756 (copy->varnum == curstack->varnum)) {
757 copy->varkind = TEMPVAR;
766 /* pop 1 push 0 store */
773 i = opcode-ICMD_ISTORE;
774 locals[iptr->op1][i].type = i;
779 count_store_length[20]++;
781 count_store_length[i]++;
784 count_store_depth[10]++;
786 count_store_depth[i]++;
788 copy = curstack->prev;
791 if ((copy->varkind == LOCALVAR) &&
792 (copy->varnum == curstack->varnum)) {
793 copy->varkind = TEMPVAR;
799 if ((new - curstack) == 1) {
800 curstack->varkind = LOCALVAR;
801 curstack->varnum = iptr->op1;
803 STORE(opcode-ICMD_ISTORE);
813 COUNT(count_check_null);
814 COUNT(count_check_bound);
815 COUNT(count_pcmd_mem);
816 OP3TIA_0(opcode-ICMD_IASTORE);
821 COUNT(count_check_null);
822 COUNT(count_check_bound);
823 COUNT(count_pcmd_mem);
838 COUNT(count_pcmd_return);
839 OP1_0(opcode-ICMD_IRETURN);
840 superblockend = true;
844 COUNT(count_check_null);
848 superblockend = true;
852 COUNT(count_pcmd_mem);
856 /* pop 1 push 0 branch */
860 COUNT(count_pcmd_bra);
862 tbptr = block + block_index[iptr->op1];
863 MARKREACHED(tbptr, copy);
872 COUNT(count_pcmd_bra);
873 #ifdef CONDITIONAL_LOADCONST
875 tbptr = block + b_index;
876 if ((b_count >= 3) &&
877 ((b_index + 2) == block_index[iptr[0].op1]) &&
878 (tbptr[1].pre_count == 1) &&
879 (iptr[1].opc == ICMD_ICONST) &&
880 (iptr[2].opc == ICMD_GOTO) &&
881 ((b_index + 3) == block_index[iptr[2].op1]) &&
882 (tbptr[2].pre_count == 1) &&
883 (iptr[3].opc == ICMD_ICONST)) {
884 OP1_1(TYPE_INT, TYPE_INT);
885 switch (iptr[0].opc) {
887 iptr[0].opc = ICMD_IFNE_ICONST;
890 iptr[0].opc = ICMD_IFEQ_ICONST;
893 iptr[0].opc = ICMD_IFGE_ICONST;
896 iptr[0].opc = ICMD_IFLT_ICONST;
899 iptr[0].opc = ICMD_IFLE_ICONST;
902 iptr[0].opc = ICMD_IFGT_ICONST;
905 iptr[0].val.i = iptr[1].val.i;
906 iptr[1].opc = ICMD_ELSE_ICONST;
907 iptr[1].val.i = iptr[3].val.i;
908 iptr[2].opc = ICMD_NOP;
909 iptr[3].opc = ICMD_NOP;
910 tbptr[1].flags = BBDELETED;
911 tbptr[2].flags = BBDELETED;
914 if (tbptr[3].pre_count == 2) {
915 len += tbptr[3].icount + 3;
916 bptr->icount += tbptr[3].icount + 3;
917 tbptr[3].flags = BBDELETED;
931 tbptr = block + block_index[iptr->op1];
932 MARKREACHED(tbptr, copy);
935 /* pop 0 push 0 branch */
938 COUNT(count_pcmd_bra);
939 tbptr = block + block_index[iptr->op1];
940 MARKREACHED(tbptr, copy);
942 superblockend = true;
945 /* pop 1 push 0 table branch */
947 case ICMD_TABLESWITCH:
948 COUNT(count_pcmd_table);
951 tbptr = block + block_index[*s4ptr++]; /* default */
952 MARKREACHED(tbptr, copy);
953 i = *s4ptr++; /* low */
954 i = *s4ptr++ - i + 1; /* high */
956 tbptr = block + block_index[*s4ptr++];
957 MARKREACHED(tbptr, copy);
960 superblockend = true;
963 /* pop 1 push 0 table branch */
965 case ICMD_LOOKUPSWITCH:
966 COUNT(count_pcmd_table);
969 tbptr = block + block_index[*s4ptr++]; /* default */
970 MARKREACHED(tbptr, copy);
971 i = *s4ptr++; /* count */
973 tbptr = block + block_index[s4ptr[1]];
974 MARKREACHED(tbptr, copy);
978 superblockend = true;
981 case ICMD_NULLCHECKPOP:
982 case ICMD_MONITORENTER:
983 COUNT(count_check_null);
984 case ICMD_MONITOREXIT:
988 /* pop 2 push 0 branch */
996 COUNT(count_pcmd_bra);
998 tbptr = block + block_index[iptr->op1];
999 MARKREACHED(tbptr, copy);
1002 case ICMD_IF_ACMPEQ:
1003 case ICMD_IF_ACMPNE:
1004 COUNT(count_pcmd_bra);
1006 tbptr = block + block_index[iptr->op1];
1007 MARKREACHED(tbptr, copy);
1013 COUNT(count_check_null);
1014 COUNT(count_pcmd_mem);
1015 OPTT2_0(iptr->op1,TYPE_ADR);
1019 if (! IS_2_WORD_TYPE(curstack->type)) {
1020 OP1_0ANY; /* second pop */
1023 iptr->opc = ICMD_POP;
1027 /* pop 0 push 1 dup */
1030 COUNT(count_dup_instruction);
1035 if (IS_2_WORD_TYPE(curstack->type)) {
1036 iptr->opc = ICMD_DUP;
1041 NEWSTACK(copy[-1].type, copy[-1].varkind,
1043 NEWSTACK(copy[ 0].type, copy[ 0].varkind,
1050 /* pop 2 push 3 dup */
1057 if (IS_2_WORD_TYPE(curstack->type)) {
1058 iptr->opc = ICMD_DUP_X1;
1066 /* pop 3 push 4 dup */
1069 if (IS_2_WORD_TYPE(curstack[-1].type)) {
1070 iptr->opc = ICMD_DUP_X1;
1079 if (IS_2_WORD_TYPE(curstack->type)) {
1080 if (IS_2_WORD_TYPE(curstack[-1].type)) {
1081 iptr->opc = ICMD_DUP_X1;
1085 iptr->opc = ICMD_DUP_X2;
1090 if (IS_2_WORD_TYPE(curstack[-2].type)) {
1091 iptr->opc = ICMD_DUP2_X1;
1099 /* pop 2 push 2 swap */
1108 if (!(SUPPORT_DIVISION)) {
1109 iptr[0].opc = ICMD_BUILTIN2;
1110 iptr[0].op1 = TYPE_INT;
1111 iptr[0].val.a = (functionptr) asm_builtin_idiv;
1112 isleafmethod = false;
1117 if (!(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV)) {
1118 iptr[0].opc = ICMD_BUILTIN2;
1119 iptr[0].op1 = TYPE_LNG;
1120 iptr[0].val.a = (functionptr) asm_builtin_ldiv;
1121 isleafmethod = false;
1126 if (!(SUPPORT_DIVISION)) {
1127 iptr[0].opc = ICMD_BUILTIN2;
1128 iptr[0].op1 = TYPE_INT;
1129 iptr[0].val.a = (functionptr) asm_builtin_irem;
1130 isleafmethod = false;
1135 if (!(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV)) {
1136 iptr[0].opc = ICMD_BUILTIN2;
1137 iptr[0].op1 = TYPE_LNG;
1138 iptr[0].val.a = (functionptr) asm_builtin_lrem;
1139 isleafmethod = false;
1153 COUNT(count_pcmd_op);
1164 COUNT(count_pcmd_op);
1171 COUNT(count_pcmd_op);
1180 COUNT(count_pcmd_op);
1189 COUNT(count_pcmd_op);
1194 COUNT(count_pcmd_op);
1195 if ((len > 0) && (iptr[1].val.i == 0)) {
1196 switch (iptr[1].opc) {
1198 iptr[0].opc = ICMD_IF_LCMPEQ;
1200 iptr[0].op1 = iptr[1].op1;
1203 /* iptr[1].opc = ICMD_NOP; */
1205 tbptr = block + block_index[iptr->op1];
1206 MARKREACHED(tbptr, copy);
1207 COUNT(count_pcmd_bra);
1210 iptr[0].opc = ICMD_IF_LCMPNE;
1211 goto icmd_lcmp_if_tail;
1213 iptr[0].opc = ICMD_IF_LCMPLT;
1214 goto icmd_lcmp_if_tail;
1216 iptr[0].opc = ICMD_IF_LCMPGT;
1217 goto icmd_lcmp_if_tail;
1219 iptr[0].opc = ICMD_IF_LCMPLE;
1220 goto icmd_lcmp_if_tail;
1222 iptr[0].opc = ICMD_IF_LCMPGE;
1223 goto icmd_lcmp_if_tail;
1225 OPTT2_1(TYPE_LNG, TYPE_INT);
1229 OPTT2_1(TYPE_LNG, TYPE_INT);
1233 COUNT(count_pcmd_op);
1234 OPTT2_1(TYPE_FLT, TYPE_INT);
1238 COUNT(count_pcmd_op);
1239 OPTT2_1(TYPE_DBL, TYPE_INT);
1247 case ICMD_INT2SHORT:
1248 COUNT(count_pcmd_op);
1249 OP1_1(TYPE_INT, TYPE_INT);
1252 COUNT(count_pcmd_op);
1253 OP1_1(TYPE_LNG, TYPE_LNG);
1256 COUNT(count_pcmd_op);
1257 OP1_1(TYPE_FLT, TYPE_FLT);
1260 COUNT(count_pcmd_op);
1261 OP1_1(TYPE_DBL, TYPE_DBL);
1265 COUNT(count_pcmd_op);
1266 OP1_1(TYPE_INT, TYPE_LNG);
1269 COUNT(count_pcmd_op);
1270 OP1_1(TYPE_INT, TYPE_FLT);
1273 COUNT(count_pcmd_op);
1274 OP1_1(TYPE_INT, TYPE_DBL);
1277 COUNT(count_pcmd_op);
1278 OP1_1(TYPE_LNG, TYPE_INT);
1281 COUNT(count_pcmd_op);
1282 OP1_1(TYPE_LNG, TYPE_FLT);
1285 COUNT(count_pcmd_op);
1286 OP1_1(TYPE_LNG, TYPE_DBL);
1289 COUNT(count_pcmd_op);
1290 OP1_1(TYPE_FLT, TYPE_INT);
1293 COUNT(count_pcmd_op);
1294 OP1_1(TYPE_FLT, TYPE_LNG);
1297 COUNT(count_pcmd_op);
1298 OP1_1(TYPE_FLT, TYPE_DBL);
1301 COUNT(count_pcmd_op);
1302 OP1_1(TYPE_DBL, TYPE_INT);
1305 COUNT(count_pcmd_op);
1306 OP1_1(TYPE_DBL, TYPE_LNG);
1309 COUNT(count_pcmd_op);
1310 OP1_1(TYPE_DBL, TYPE_FLT);
1313 case ICMD_CHECKCAST:
1314 OP1_1(TYPE_ADR, TYPE_ADR);
1317 case ICMD_ARRAYLENGTH:
1318 case ICMD_INSTANCEOF:
1319 OP1_1(TYPE_ADR, TYPE_INT);
1323 case ICMD_ANEWARRAY:
1324 OP1_1(TYPE_INT, TYPE_ADR);
1328 COUNT(count_check_null);
1329 COUNT(count_pcmd_mem);
1330 OP1_1(TYPE_ADR, iptr->op1);
1335 case ICMD_GETSTATIC:
1336 COUNT(count_pcmd_mem);
1346 tbptr = block + block_index[iptr->op1];
1347 tbptr->type=BBTYPE_SBR;
1348 MARKREACHED(tbptr, copy);
1352 /* pop many push any */
1354 case ICMD_INVOKEVIRTUAL:
1355 case ICMD_INVOKESPECIAL:
1356 case ICMD_INVOKEINTERFACE:
1357 case ICMD_INVOKESTATIC:
1358 COUNT(count_pcmd_met);
1360 methodinfo *m = iptr->val.a;
1361 if (m->flags & ACC_STATIC)
1362 {COUNT(count_check_null);}
1364 if (i > arguments_num)
1368 if (! (copy->flags & SAVEDVAR)) {
1369 copy->varkind = ARGVAR;
1375 copy->flags |= SAVEDVAR;
1380 if (m->returntype != TYPE_VOID) {
1381 OP0_1(m->returntype);
1387 if (! (curstack->flags & SAVEDVAR)) {
1388 curstack->varkind = ARGVAR;
1389 curstack->varnum = 2;
1394 if (! (curstack->flags & SAVEDVAR)) {
1395 curstack->varkind = ARGVAR;
1396 curstack->varnum = 1;
1400 if (! (curstack->flags & SAVEDVAR)) {
1401 curstack->varkind = ARGVAR;
1402 curstack->varnum = 0;
1407 copy->flags |= SAVEDVAR;
1410 if (iptr->op1 != TYPE_VOID)
1414 case ICMD_MULTIANEWARRAY:
1416 if ((i + intreg_argnum) > arguments_num)
1417 arguments_num = i + intreg_argnum;
1420 if (! (copy->flags & SAVEDVAR)) {
1421 copy->varkind = ARGVAR;
1422 copy->varnum = i + intreg_argnum;
1427 copy->flags |= SAVEDVAR;
1436 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1437 panic("Missing ICMD code during stack analysis");
1440 } /* while instructions */
1441 bptr->outstack = curstack;
1442 bptr->outdepth = stackdepth;
1446 superblockend = true;
1448 } /* while blocks */
1449 } while (repeat && ! deadcode);
1452 if (block_count > count_max_basic_blocks)
1453 count_max_basic_blocks = block_count;
1454 count_basic_blocks += block_count;
1455 if (instr_count > count_max_javainstr)
1456 count_max_javainstr = instr_count;
1457 count_javainstr += instr_count;
1458 if (stack_count > count_upper_bound_new_stack)
1459 count_upper_bound_new_stack = stack_count;
1460 if ((new - stack) > count_max_new_stack)
1461 count_max_new_stack = (new - stack);
1463 b_count = block_count;
1465 while (--b_count >= 0) {
1466 if (bptr->flags > BBREACHED) {
1467 if (bptr->indepth >= 10)
1468 count_block_stack[10]++;
1470 count_block_stack[bptr->indepth]++;
1473 count_block_size_distribution[len - 1]++;
1475 count_block_size_distribution[10]++;
1477 count_block_size_distribution[11]++;
1479 count_block_size_distribution[12]++;
1481 count_block_size_distribution[13]++;
1483 count_block_size_distribution[14]++;
1485 count_block_size_distribution[15]++;
1487 count_block_size_distribution[16]++;
1489 count_block_size_distribution[17]++;
1495 count_analyse_iterations[0]++;
1496 else if (loops == 2)
1497 count_analyse_iterations[1]++;
1498 else if (loops == 3)
1499 count_analyse_iterations[2]++;
1500 else if (loops == 4)
1501 count_analyse_iterations[3]++;
1503 count_analyse_iterations[4]++;
1505 if (block_count <= 5)
1506 count_method_bb_distribution[0]++;
1507 else if (block_count <= 10)
1508 count_method_bb_distribution[1]++;
1509 else if (block_count <= 15)
1510 count_method_bb_distribution[2]++;
1511 else if (block_count <= 20)
1512 count_method_bb_distribution[3]++;
1513 else if (block_count <= 30)
1514 count_method_bb_distribution[4]++;
1515 else if (block_count <= 40)
1516 count_method_bb_distribution[5]++;
1517 else if (block_count <= 50)
1518 count_method_bb_distribution[6]++;
1519 else if (block_count <= 75)
1520 count_method_bb_distribution[7]++;
1522 count_method_bb_distribution[8]++;
1527 static void print_stack(stackptr s) {
1543 if (s->flags & SAVEDVAR)
1544 switch (s->varkind) {
1546 if (s->flags & INMEMORY)
1547 printf(" m%02d", s->regoff);
1549 printf(" r%02d", s->regoff);
1552 printf(" s%02d", s->varnum);
1555 printf(" l%02d", s->varnum);
1558 printf(" a%02d", s->varnum);
1561 printf(" !%02d", j);
1564 switch (s->varkind) {
1566 if (s->flags & INMEMORY)
1567 printf(" M%02d", s->regoff);
1569 printf(" R%02d", s->regoff);
1572 printf(" S%02d", s->varnum);
1575 printf(" L%02d", s->varnum);
1578 printf(" A%02d", s->varnum);
1581 printf(" ?%02d", j);
1588 static void print_reg(stackptr s) {
1590 if (s->flags & SAVEDVAR)
1591 switch (s->varkind) {
1593 if (s->flags & INMEMORY)
1594 printf(" tm%02d", s->regoff);
1596 printf(" tr%02d", s->regoff);
1599 printf(" s %02d", s->varnum);
1602 printf(" l %02d", s->varnum);
1605 printf(" a %02d", s->varnum);
1608 printf(" ! %02d", s->varnum);
1611 switch (s->varkind) {
1613 if (s->flags & INMEMORY)
1614 printf(" Tm%02d", s->regoff);
1616 printf(" Tr%02d", s->regoff);
1619 printf(" S %02d", s->varnum);
1622 printf(" L %02d", s->varnum);
1625 printf(" A %02d", s->varnum);
1628 printf(" ? %02d", s->varnum);
1637 static char *builtin_name(functionptr bptr)
1639 builtin_descriptor *bdesc = builtin_desc;
1640 while ((bdesc->bptr != NULL) && (bdesc->bptr != bptr))
1646 static void show_icmd_method()
1654 unicode_fprint(stdout, class->name);
1656 unicode_fprint(stdout, method->name);
1658 unicode_fprint(stdout, method->descriptor);
1659 printf ("\n\nMax locals: %d\n", (int) maxlocals);
1660 printf ("Max stack: %d\n", (int) maxstack);
1662 printf ("Exceptions:\n");
1663 for (i = 0; i < exceptiontablelength; i++) {
1664 printf(" L%03d ... ", block_index[extable[i].startpc]);
1665 printf("L%03d = ", block_index[extable[i].endpc]);
1666 printf("L%03d\n", block_index[extable[i].handlerpc]);
1669 printf ("Local Table:\n");
1670 for (i = 0; i < maxlocals; i++) {
1671 printf(" %3d: ", i);
1672 for (j = TYPE_INT; j <= TYPE_ADR; j++)
1673 if (locals[i][j].type >= 0) {
1674 printf(" (%d) ", j);
1675 if (locals[i][j].flags)
1679 printf("%2d", locals[i][j].regoff);
1685 printf ("Interface Table:\n");
1686 for (i = 0; i < maxstack; i++) {
1687 if ((interfaces[i][0].type >= 0) || (interfaces[i][1].type >= 0) ||
1688 (interfaces[i][2].type >= 0) || (interfaces[i][3].type >= 0) ||
1689 (interfaces[i][4].type >= 0)) {
1690 printf(" %3d: ", i);
1691 for (j = TYPE_INT; j <= TYPE_ADR; j++)
1692 if (interfaces[i][j].type >= 0) {
1693 printf(" (%d) ", j);
1694 if (interfaces[i][j].flags & SAVEDVAR)
1698 if (interfaces[i][j].flags & INMEMORY)
1702 printf("%2d", interfaces[i][j].regoff);
1709 if (showdisassemble) {
1710 s4ptr = (s4 *) (method->mcode + dseglen);
1711 for (i = 0; i < block[0].mpc; i += 4, s4ptr++) {
1712 disassinstr(*s4ptr, i);
1717 for (b = 0; b < block_count; b++)
1718 if (block[b].flags != BBDELETED) {
1719 deadcode = block[b].flags <= BBREACHED;
1722 for (j = maxstack; j > 0; j--)
1725 print_stack(block[b].instack);
1726 printf("] L%03d(%d):\n", b, block[b].pre_count);
1727 iptr = block[b].iinstr;
1729 for (last = i + block[b].icount; i < last; i++, iptr++) {
1732 for (j = maxstack; j > 0; j--)
1736 print_stack(iptr->dst);
1737 printf("] %4d %s", i, icmd_names[iptr->opc]);
1738 switch ((int) iptr->opc) {
1739 case ICMD_IADDCONST:
1740 case ICMD_ISUBCONST:
1741 case ICMD_IMULCONST:
1744 case ICMD_IREM0X10001:
1745 case ICMD_IANDCONST:
1747 case ICMD_IXORCONST:
1748 case ICMD_ISHLCONST:
1749 case ICMD_ISHRCONST:
1750 case ICMD_IUSHRCONST:
1752 case ICMD_ELSE_ICONST:
1753 case ICMD_IFEQ_ICONST:
1754 case ICMD_IFNE_ICONST:
1755 case ICMD_IFLT_ICONST:
1756 case ICMD_IFGE_ICONST:
1757 case ICMD_IFGT_ICONST:
1758 case ICMD_IFLE_ICONST:
1759 printf(" %d", iptr->val.i);
1761 case ICMD_LADDCONST:
1762 case ICMD_LSUBCONST:
1763 case ICMD_LMULCONST:
1766 case ICMD_LANDCONST:
1768 case ICMD_LXORCONST:
1769 case ICMD_LSHLCONST:
1770 case ICMD_LSHRCONST:
1771 case ICMD_LUSHRCONST:
1773 printf(" %ld", iptr->val.l);
1776 printf(" %f", iptr->val.f);
1779 printf(" %f", iptr->val.d);
1782 printf(" %p", iptr->val.a);
1786 printf(" %d,", ((fieldinfo *) iptr->val.a)->offset);
1787 case ICMD_PUTSTATIC:
1788 case ICMD_GETSTATIC:
1790 unicode_fprint(stdout,
1791 ((fieldinfo *) iptr->val.a)->name);
1794 printf(" %d + %d", iptr->op1, iptr->val.i);
1807 printf(" %d", iptr->op1);
1811 unicode_fprint(stdout,
1812 ((classinfo *) iptr->val.a)->name);
1815 switch (iptr->op1) {
1842 case ICMD_ANEWARRAY:
1845 unicode_fprint(stdout,
1846 ((classinfo *) iptr->val.a)->name);
1849 case ICMD_CHECKCAST:
1850 case ICMD_INSTANCEOF:
1852 classinfo *c = iptr->val.a;
1853 if (c->flags & ACC_INTERFACE)
1854 printf(" (INTERFACE) ");
1856 printf(" (CLASS,%3d) ", c->vftbl->diffval);
1857 unicode_fprint(stdout, c->name);
1863 printf(" %s", builtin_name((functionptr) iptr->val.a));
1865 case ICMD_INVOKEVIRTUAL:
1866 case ICMD_INVOKESPECIAL:
1867 case ICMD_INVOKESTATIC:
1868 case ICMD_INVOKEINTERFACE:
1870 unicode_fprint(stdout,
1871 ((methodinfo *) iptr->val.a)->class->name);
1873 unicode_fprint(stdout,
1874 ((methodinfo *) iptr->val.a)->name);
1888 printf("(%d) L%03d", iptr->val.i, block_index[iptr->op1]);
1893 case ICMD_IFNONNULL:
1894 case ICMD_IF_ICMPEQ:
1895 case ICMD_IF_ICMPNE:
1896 case ICMD_IF_ICMPLT:
1897 case ICMD_IF_ICMPGE:
1898 case ICMD_IF_ICMPGT:
1899 case ICMD_IF_ICMPLE:
1900 case ICMD_IF_LCMPEQ:
1901 case ICMD_IF_LCMPNE:
1902 case ICMD_IF_LCMPLT:
1903 case ICMD_IF_LCMPGE:
1904 case ICMD_IF_LCMPGT:
1905 case ICMD_IF_LCMPLE:
1906 case ICMD_IF_ACMPEQ:
1907 case ICMD_IF_ACMPNE:
1908 printf(" L%03d", block_index[iptr->op1]);
1910 case ICMD_TABLESWITCH:
1911 s4ptr = iptr->val.a;
1912 printf(" L%03d;", block_index[*s4ptr++]); /* default */
1913 j = *s4ptr++; /* low */
1914 j = *s4ptr++ - j; /* high */
1916 printf(" L%03d", block_index[*s4ptr++]);
1920 case ICMD_LOOKUPSWITCH:
1921 s4ptr = iptr->val.a;
1922 printf(" L%d", block_index[*s4ptr++]); /* default */
1923 j = *s4ptr++; /* count */
1925 printf(" L%03d", block_index[s4ptr[1]]);
1933 if (showdisassemble && (!deadcode)) {
1936 s4ptr = (s4 *) (method->mcode + dseglen + i);
1937 for (; i < block[b + 1].mpc; i += 4, s4ptr++) {
1938 disassinstr(*s4ptr, i);
1944 s4ptr = (s4 *) (method->mcode + dseglen + i);
1945 if (showdisassemble && (s4ptr < (s4 *) (method->mcode + method->mcodelength))) {
1947 for (; s4ptr < (s4 *) (method->mcode + method->mcodelength); i += 4, s4ptr++) {
1948 disassinstr(*s4ptr, i);
1956 * These are local overrides for various environment variables in Emacs.
1957 * Please do not remove this and leave it at the end of the file, where
1958 * Emacs will automagically detect them.
1959 * ---------------------------------------------------------------------
1962 * indent-tabs-mode: t