1 /* jit/stack.c - stack analysis
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
29 Changes: Edwin Steiner
31 $Id: stack.c 974 2004-03-25 17:31:13Z jowenn $
47 #include "toolbox/loging.h"
48 #include "toolbox/memory.h"
51 /* from codegen.inc */
54 /**********************************************************************/
55 /* Macros used internally by analyse_stack */
56 /**********************************************************************/
59 #define COUNT(cnt) cnt++
64 /* convenient abbreviations */
65 #define CURKIND curstack->varkind
66 #define CURTYPE curstack->type
68 /*--------------------------------------------------*/
69 /* SIGNALING ERRORS */
70 /*--------------------------------------------------*/
72 #define TYPEPANIC {show_icmd_method();panic("Stack type mismatch");}
73 #define UNDERFLOW {show_icmd_method();panic("Operand stack underflow");}
74 #define OVERFLOW {show_icmd_method();panic("Operand stack overflow");}
76 /*--------------------------------------------------*/
77 /* STACK UNDERFLOW/OVERFLOW CHECKS */
78 /*--------------------------------------------------*/
80 /* underflow checks */
81 #define REQUIRE(num) do { if (stackdepth<(num)) {UNDERFLOW;} } while(0)
82 #define REQUIRE_1 REQUIRE(1)
83 #define REQUIRE_2 REQUIRE(2)
84 #define REQUIRE_3 REQUIRE(3)
85 #define REQUIRE_4 REQUIRE(4)
88 /* We allow ACONST instructions inserted as arguments to builtin
89 * functions to exceed the maximum stack depth. Maybe we should check
90 * against maximum stack depth only at block boundaries?
92 #define CHECKOVERFLOW \
94 if (stackdepth > maxstack) { \
95 if (iptr[0].opc != ICMD_ACONST \
96 || iptr[0].op1 == 0) \
101 /*--------------------------------------------------*/
102 /* ALLOCATING STACK SLOTS */
103 /*--------------------------------------------------*/
105 #define NEWSTACK(s,v,n) {new->prev=curstack;new->type=s;new->flags=0; \
106 new->varkind=v;new->varnum=n;curstack=new;new++;}
107 #define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
108 #define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
110 /* allocate the input stack for an exception handler */
111 #define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
113 /*--------------------------------------------------*/
114 /* STACK MANIPULATION */
115 /*--------------------------------------------------*/
117 /* resetting to an empty operand stack */
118 #define STACKRESET {curstack=0;stackdepth=0;}
120 /* set the output stack of the current instruction */
121 #define SETDST {iptr->dst=curstack;}
123 /* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
124 #define POP(s) {if(s!=curstack->type){TYPEPANIC;} \
125 if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
126 curstack=curstack->prev;}
127 #define POPANY {if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR; \
128 curstack=curstack->prev;}
129 #define COPY(s,d) {(d)->flags=0;(d)->type=(s)->type;\
130 (d)->varkind=(s)->varkind;(d)->varnum=(s)->varnum;}
132 /*--------------------------------------------------*/
133 /* STACK OPERATIONS MODELING */
134 /*--------------------------------------------------*/
136 /* The following macros are used to model the stack manipulations of
137 * different kinds of instructions.
139 * These macros check the input stackdepth and they set the output
140 * stackdepth and the output stack of the instruction (iptr->dst).
142 * These macros do *not* check for stack overflows!
145 #define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
146 #define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
147 #define STORE(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
148 #define OP1_0(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
149 #define OP1_0ANY {REQUIRE_1;POPANY;SETDST;stackdepth--;}
150 #define OP0_1(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
151 #define OP1_1(s,d) {REQUIRE_1;POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
152 #define OP2_0(s) {REQUIRE_2;POP(s);POP(s);SETDST;stackdepth-=2;}
153 #define OPTT2_0(t,b){REQUIRE_2;POP(t);POP(b);SETDST;stackdepth-=2;}
154 #define OP2_1(s) {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
155 #define OP2IAT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
156 SETDST;stackdepth--;}
157 #define OP2IT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
158 SETDST;stackdepth--;}
159 #define OPTT2_1(s,d){REQUIRE_2;POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
160 #define OP2_2(s) {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
161 NEWSTACKn(s,stackdepth-1);SETDST;}
162 #define OP3TIA_0(s) {REQUIRE_3;POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
163 #define OP3_0(s) {REQUIRE_3;POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
164 #define POPMANY(i) {REQUIRE(i);stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
165 #define DUP {REQUIRE_1;NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
167 #define SWAP {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
168 new[0].prev=curstack;new[1].prev=new;\
169 curstack=new+1;new+=2;SETDST;}
170 #define DUP_X1 {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
171 COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
172 new[1].prev=new;new[2].prev=new+1;\
173 curstack=new+2;new+=3;SETDST;stackdepth++;}
174 #define DUP2_X1 {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
175 COPY(curstack,new);COPY(curstack,new+3);POPANY;\
176 COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
177 new[1].prev=new;new[2].prev=new+1;\
178 new[3].prev=new+2;new[4].prev=new+3;\
179 curstack=new+4;new+=5;SETDST;stackdepth+=2;}
180 #define DUP_X2 {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
181 COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
182 new[0].prev=curstack;new[1].prev=new;\
183 new[2].prev=new+1;new[3].prev=new+2;\
184 curstack=new+3;new+=4;SETDST;stackdepth++;}
185 #define DUP2_X2 {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
186 COPY(curstack,new);COPY(curstack,new+4);POPANY;\
187 COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
188 new[0].prev=curstack;new[1].prev=new;\
189 new[2].prev=new+1;new[3].prev=new+2;\
190 new[4].prev=new+3;new[5].prev=new+4;\
191 curstack=new+5;new+=6;SETDST;stackdepth+=2;}
193 /*--------------------------------------------------*/
194 /* MACROS FOR HANDLING BASIC BLOCKS */
195 /*--------------------------------------------------*/
197 /* COPYCURSTACK makes a copy of the current operand stack (curstack)
198 * and returns it in the variable copy.
200 * This macro is used to propagate the operand stack from one basic
201 * block to another. The destination block receives the copy as its
204 #define COPYCURSTACK(copy) {\
217 copy->varkind=STACKVAR;\
228 /* BBEND is called at the end of each basic block (after the last
229 * instruction of the block has been processed).
236 if((copy->varkind==STACKVAR)&&(copy->varnum>i))\
237 copy->varkind=TEMPVAR;\
239 copy->varkind=STACKVAR;\
242 interfaces[i][copy->type].type = copy->type;\
243 interfaces[i][copy->type].flags |= copy->flags;\
244 i--;copy=copy->prev;\
249 interfaces[i][copy->type].type = copy->type;\
250 if(copy->varkind==STACKVAR){\
251 if (copy->flags & SAVEDVAR)\
252 interfaces[i][copy->type].flags |= SAVEDVAR;\
254 i--;copy=copy->prev;\
259 /* MARKREACHED marks the destination block <b> as reached. If this
260 * block has been reached before we check if stack depth and types
261 * match. Otherwise the destination block receives a copy of the
262 * current stack as its input stack.
264 * b...destination block
267 #define MARKREACHED(b,c) { \
269 {COPYCURSTACK(c);b->flags=0;b->instack=c;b->indepth=stackdepth;} \
270 else {stackptr s=curstack;stackptr t=b->instack; \
271 if(b->indepth!=stackdepth) \
272 {show_icmd_method();panic("Stack depth mismatch");} \
273 while(s){if (s->type!=t->type) \
275 s=s->prev;t=t->prev; \
281 /**********************************************************************/
283 /**********************************************************************/
285 /* analyse_stack uses the intermediate code created by parse.c to
286 * build a model of the JVM operand stack for the current method.
288 * The following checks are performed:
289 * - check for operand stack underflow (before each instruction)
290 * - check for operand stack overflow (after[1] each instruction)
291 * - check for matching stack depth at merging points
292 * - check for matching basic types[2] at merging points
293 * - check basic types for instruction input (except for BUILTIN*
294 * opcodes, INVOKE* opcodes and MULTIANEWARRAY)
296 * [1]) Checking this after the instruction should be ok. parse.c
297 * counts the number of required stack slots in such a way that it is
298 * only vital that we don't exceed `maxstack` at basic block
301 * [2]) 'basic types' means the distinction between INT, LONG, FLOAT,
302 * DOUBLE and ADDRESS types. Subtypes of INT and different ADDRESS
303 * types are not discerned.
314 int opcode, i, len, loops;
315 int superblockend, repeat, deadcode;
323 if (compileverbose) {
324 char logtext[MAXLOGTEXT];
325 sprintf(logtext, "Analysing: ");
326 utf_sprint(logtext+strlen(logtext), method->class->name);
327 strcpy(logtext+strlen(logtext), ".");
328 utf_sprint(logtext+strlen(logtext), method->name);
329 utf_sprint(logtext+strlen(logtext), method->descriptor);
333 argren = DMNEW(int, maxlocals);
334 /*int *argren = (int *)alloca(maxlocals * sizeof(int));*/ /* table for argument renaming */
335 for (i = 0; i < maxlocals; i++)
341 block[0].flags = BBREACHED;
342 block[0].instack = 0;
343 block[0].indepth = 0;
345 for (i = 0; i < exceptiontablelength; i++) {
346 bptr = &block[block_index[extable[i].handlerpc]];
347 bptr->flags = BBREACHED;
348 bptr->type = BBTYPE_EXH;
351 bptr->pre_count = 10000;
356 #ifdef CONDITIONAL_LOADCONST
357 b_count = block_count;
359 while (--b_count >= 0) {
360 if (bptr->icount != 0) {
361 iptr = bptr->iinstr + bptr->icount - 1;
394 block[block_index[iptr->op1]].pre_count++;
397 case ICMD_TABLESWITCH:
399 block[block_index[*s4ptr++]].pre_count++; /* default */
400 i = *s4ptr++; /* low */
401 i = *s4ptr++ - i + 1; /* high */
403 block[block_index[*s4ptr++]].pre_count++;
407 case ICMD_LOOKUPSWITCH:
409 block[block_index[*s4ptr++]].pre_count++; /* default */
410 i = *s4ptr++; /* count */
412 block[block_index[s4ptr[1]]].pre_count++;
428 b_count = block_count;
430 superblockend = true;
434 while (--b_count >= 0) {
435 if (bptr->flags == BBDELETED) {
438 else if (superblockend && (bptr->flags < BBREACHED))
440 else if (bptr->flags <= BBREACHED) {
442 stackdepth = bptr->indepth;
443 else if (bptr->flags < BBREACHED) {
445 bptr->instack = copy;
446 bptr->indepth = stackdepth;
448 else if (bptr->indepth != stackdepth) {
450 panic("Stack depth mismatch");
453 curstack = bptr->instack;
455 superblockend = false;
456 bptr->flags = BBFINISHED;
459 b_index = bptr - block;
464 /* DEBUG */ /* dolog("p:%04d op: %s",iptr-instr,icmd_names[opcode]); */
466 #ifdef USEBUILTINTABLE
469 stdopdescriptor *breplace;
470 breplace = find_builtin(opcode);
472 if (breplace && opcode == breplace->opcode) {
473 iptr[0].opc = breplace->icmd;
474 iptr[0].op1 = breplace->type_d;
475 iptr[0].val.a = breplace->builtin;
476 isleafmethod = false;
477 switch (breplace->icmd) {
485 builtin_descriptor *breplace;
486 breplace = find_builtin(opcode);
488 if (breplace && opcode == breplace->opcode) {
489 iptr[0].opc = breplace->icmd;
490 iptr[0].op1 = breplace->type_d;
491 iptr[0].val.a = breplace->builtin;
492 isleafmethod = false;
493 switch (breplace->icmd) {
508 case ICMD_CHECKASIZE:
510 case ICMD_IFEQ_ICONST:
511 case ICMD_IFNE_ICONST:
512 case ICMD_IFLT_ICONST:
513 case ICMD_IFGE_ICONST:
514 case ICMD_IFGT_ICONST:
515 case ICMD_IFLE_ICONST:
516 case ICMD_ELSE_ICONST:
521 locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
523 COUNT(count_pcmd_return);
525 superblockend = true;
528 /* pop 0 push 1 const */
531 COUNT(count_pcmd_load);
533 switch (iptr[1].opc) {
535 iptr[0].opc = ICMD_IADDCONST;
537 iptr[1].opc = ICMD_NOP;
538 OP1_1(TYPE_INT,TYPE_INT);
539 COUNT(count_pcmd_op);
542 iptr[0].opc = ICMD_ISUBCONST;
543 goto icmd_iconst_tail;
545 iptr[0].opc = ICMD_IMULCONST;
546 goto icmd_iconst_tail;
548 if (iptr[0].val.i == 0x00000002)
550 else if (iptr[0].val.i == 0x00000004)
552 else if (iptr[0].val.i == 0x00000008)
554 else if (iptr[0].val.i == 0x00000010)
556 else if (iptr[0].val.i == 0x00000020)
558 else if (iptr[0].val.i == 0x00000040)
560 else if (iptr[0].val.i == 0x00000080)
562 else if (iptr[0].val.i == 0x00000100)
564 else if (iptr[0].val.i == 0x00000200)
566 else if (iptr[0].val.i == 0x00000400)
568 else if (iptr[0].val.i == 0x00000800)
570 else if (iptr[0].val.i == 0x00001000)
572 else if (iptr[0].val.i == 0x00002000)
574 else if (iptr[0].val.i == 0x00004000)
576 else if (iptr[0].val.i == 0x00008000)
578 else if (iptr[0].val.i == 0x00010000)
580 else if (iptr[0].val.i == 0x00020000)
582 else if (iptr[0].val.i == 0x00040000)
584 else if (iptr[0].val.i == 0x00080000)
586 else if (iptr[0].val.i == 0x00100000)
588 else if (iptr[0].val.i == 0x00200000)
590 else if (iptr[0].val.i == 0x00400000)
592 else if (iptr[0].val.i == 0x00800000)
594 else if (iptr[0].val.i == 0x01000000)
596 else if (iptr[0].val.i == 0x02000000)
598 else if (iptr[0].val.i == 0x04000000)
600 else if (iptr[0].val.i == 0x08000000)
602 else if (iptr[0].val.i == 0x10000000)
604 else if (iptr[0].val.i == 0x20000000)
606 else if (iptr[0].val.i == 0x40000000)
608 else if (iptr[0].val.i == 0x80000000)
614 iptr[0].opc = ICMD_IDIVPOW2;
615 goto icmd_iconst_tail;
617 #if !defined(NO_DIV_OPT)
618 if (iptr[0].val.i == 0x10001) {
619 iptr[0].opc = ICMD_IREM0X10001;
620 goto icmd_iconst_tail;
623 if ((iptr[0].val.i == 0x00000002) ||
624 (iptr[0].val.i == 0x00000004) ||
625 (iptr[0].val.i == 0x00000008) ||
626 (iptr[0].val.i == 0x00000010) ||
627 (iptr[0].val.i == 0x00000020) ||
628 (iptr[0].val.i == 0x00000040) ||
629 (iptr[0].val.i == 0x00000080) ||
630 (iptr[0].val.i == 0x00000100) ||
631 (iptr[0].val.i == 0x00000200) ||
632 (iptr[0].val.i == 0x00000400) ||
633 (iptr[0].val.i == 0x00000800) ||
634 (iptr[0].val.i == 0x00001000) ||
635 (iptr[0].val.i == 0x00002000) ||
636 (iptr[0].val.i == 0x00004000) ||
637 (iptr[0].val.i == 0x00008000) ||
638 (iptr[0].val.i == 0x00010000) ||
639 (iptr[0].val.i == 0x00020000) ||
640 (iptr[0].val.i == 0x00040000) ||
641 (iptr[0].val.i == 0x00080000) ||
642 (iptr[0].val.i == 0x00100000) ||
643 (iptr[0].val.i == 0x00200000) ||
644 (iptr[0].val.i == 0x00400000) ||
645 (iptr[0].val.i == 0x00800000) ||
646 (iptr[0].val.i == 0x01000000) ||
647 (iptr[0].val.i == 0x02000000) ||
648 (iptr[0].val.i == 0x04000000) ||
649 (iptr[0].val.i == 0x08000000) ||
650 (iptr[0].val.i == 0x10000000) ||
651 (iptr[0].val.i == 0x20000000) ||
652 (iptr[0].val.i == 0x40000000) ||
653 (iptr[0].val.i == 0x80000000)) {
654 iptr[0].opc = ICMD_IREMPOW2;
656 goto icmd_iconst_tail;
661 iptr[0].opc = ICMD_IANDCONST;
662 goto icmd_iconst_tail;
664 iptr[0].opc = ICMD_IORCONST;
665 goto icmd_iconst_tail;
667 iptr[0].opc = ICMD_IXORCONST;
668 goto icmd_iconst_tail;
670 iptr[0].opc = ICMD_ISHLCONST;
671 goto icmd_iconst_tail;
673 iptr[0].opc = ICMD_ISHRCONST;
674 goto icmd_iconst_tail;
676 iptr[0].opc = ICMD_IUSHRCONST;
677 goto icmd_iconst_tail;
678 #if SUPPORT_LONG_SHIFT
680 iptr[0].opc = ICMD_LSHLCONST;
681 goto icmd_lconst_tail;
683 iptr[0].opc = ICMD_LSHRCONST;
684 goto icmd_lconst_tail;
686 iptr[0].opc = ICMD_LUSHRCONST;
687 goto icmd_lconst_tail;
690 iptr[0].opc = ICMD_IFEQ;
692 iptr[0].op1 = iptr[1].op1;
695 /* iptr[1].opc = ICMD_NOP; */
697 tbptr = block + block_index[iptr->op1];
699 iptr[0].target = (void *) tbptr;
701 MARKREACHED(tbptr, copy);
702 COUNT(count_pcmd_bra);
705 iptr[0].opc = ICMD_IFLT;
706 goto icmd_if_icmp_tail;
708 iptr[0].opc = ICMD_IFLE;
709 goto icmd_if_icmp_tail;
711 iptr[0].opc = ICMD_IFNE;
712 goto icmd_if_icmp_tail;
714 iptr[0].opc = ICMD_IFGT;
715 goto icmd_if_icmp_tail;
717 iptr[0].opc = ICMD_IFGE;
718 goto icmd_if_icmp_tail;
727 COUNT(count_pcmd_load);
729 switch (iptr[1].opc) {
732 iptr[0].opc = ICMD_LADDCONST;
734 iptr[1].opc = ICMD_NOP;
735 OP1_1(TYPE_LNG,TYPE_LNG);
736 COUNT(count_pcmd_op);
739 iptr[0].opc = ICMD_LSUBCONST;
740 goto icmd_lconst_tail;
744 iptr[0].opc = ICMD_LMULCONST;
745 #if defined(__I386__)
746 method_uses_edx = true;
748 goto icmd_lconst_tail;
752 if (iptr[0].val.l == 0x00000002)
754 else if (iptr[0].val.l == 0x00000004)
756 else if (iptr[0].val.l == 0x00000008)
758 else if (iptr[0].val.l == 0x00000010)
760 else if (iptr[0].val.l == 0x00000020)
762 else if (iptr[0].val.l == 0x00000040)
764 else if (iptr[0].val.l == 0x00000080)
766 else if (iptr[0].val.l == 0x00000100)
768 else if (iptr[0].val.l == 0x00000200)
770 else if (iptr[0].val.l == 0x00000400)
772 else if (iptr[0].val.l == 0x00000800)
774 else if (iptr[0].val.l == 0x00001000)
776 else if (iptr[0].val.l == 0x00002000)
778 else if (iptr[0].val.l == 0x00004000)
780 else if (iptr[0].val.l == 0x00008000)
782 else if (iptr[0].val.l == 0x00010000)
784 else if (iptr[0].val.l == 0x00020000)
786 else if (iptr[0].val.l == 0x00040000)
788 else if (iptr[0].val.l == 0x00080000)
790 else if (iptr[0].val.l == 0x00100000)
792 else if (iptr[0].val.l == 0x00200000)
794 else if (iptr[0].val.l == 0x00400000)
796 else if (iptr[0].val.l == 0x00800000)
798 else if (iptr[0].val.l == 0x01000000)
800 else if (iptr[0].val.l == 0x02000000)
802 else if (iptr[0].val.l == 0x04000000)
804 else if (iptr[0].val.l == 0x08000000)
806 else if (iptr[0].val.l == 0x10000000)
808 else if (iptr[0].val.l == 0x20000000)
810 else if (iptr[0].val.l == 0x40000000)
812 else if (iptr[0].val.l == 0x80000000)
818 iptr[0].opc = ICMD_LDIVPOW2;
819 goto icmd_lconst_tail;
821 #if !defined(NO_DIV_OPT)
822 if (iptr[0].val.l == 0x10001) {
823 iptr[0].opc = ICMD_LREM0X10001;
824 goto icmd_lconst_tail;
827 if ((iptr[0].val.l == 0x00000002) ||
828 (iptr[0].val.l == 0x00000004) ||
829 (iptr[0].val.l == 0x00000008) ||
830 (iptr[0].val.l == 0x00000010) ||
831 (iptr[0].val.l == 0x00000020) ||
832 (iptr[0].val.l == 0x00000040) ||
833 (iptr[0].val.l == 0x00000080) ||
834 (iptr[0].val.l == 0x00000100) ||
835 (iptr[0].val.l == 0x00000200) ||
836 (iptr[0].val.l == 0x00000400) ||
837 (iptr[0].val.l == 0x00000800) ||
838 (iptr[0].val.l == 0x00001000) ||
839 (iptr[0].val.l == 0x00002000) ||
840 (iptr[0].val.l == 0x00004000) ||
841 (iptr[0].val.l == 0x00008000) ||
842 (iptr[0].val.l == 0x00010000) ||
843 (iptr[0].val.l == 0x00020000) ||
844 (iptr[0].val.l == 0x00040000) ||
845 (iptr[0].val.l == 0x00080000) ||
846 (iptr[0].val.l == 0x00100000) ||
847 (iptr[0].val.l == 0x00200000) ||
848 (iptr[0].val.l == 0x00400000) ||
849 (iptr[0].val.l == 0x00800000) ||
850 (iptr[0].val.l == 0x01000000) ||
851 (iptr[0].val.l == 0x02000000) ||
852 (iptr[0].val.l == 0x04000000) ||
853 (iptr[0].val.l == 0x08000000) ||
854 (iptr[0].val.l == 0x10000000) ||
855 (iptr[0].val.l == 0x20000000) ||
856 (iptr[0].val.l == 0x40000000) ||
857 (iptr[0].val.l == 0x80000000)) {
858 iptr[0].opc = ICMD_LREMPOW2;
860 goto icmd_lconst_tail;
867 iptr[0].opc = ICMD_LANDCONST;
868 goto icmd_lconst_tail;
870 iptr[0].opc = ICMD_LORCONST;
871 goto icmd_lconst_tail;
873 iptr[0].opc = ICMD_LXORCONST;
874 goto icmd_lconst_tail;
876 #if !defined(NOLONG_CONDITIONAL)
878 if ((len > 1) && (iptr[2].val.i == 0)) {
879 switch (iptr[2].opc) {
881 iptr[0].opc = ICMD_IF_LEQ;
882 icmd_lconst_lcmp_tail:
883 iptr[0].op1 = iptr[2].op1;
886 /* iptr[1].opc = ICMD_NOP;
887 iptr[2].opc = ICMD_NOP; */
889 tbptr = block + block_index[iptr->op1];
891 iptr[0].target = (void *) tbptr;
893 MARKREACHED(tbptr, copy);
894 COUNT(count_pcmd_bra);
895 COUNT(count_pcmd_op);
898 iptr[0].opc = ICMD_IF_LNE;
899 goto icmd_lconst_lcmp_tail;
901 iptr[0].opc = ICMD_IF_LLT;
902 goto icmd_lconst_lcmp_tail;
904 iptr[0].opc = ICMD_IF_LGT;
905 goto icmd_lconst_lcmp_tail;
907 iptr[0].opc = ICMD_IF_LLE;
908 goto icmd_lconst_lcmp_tail;
910 iptr[0].opc = ICMD_IF_LGE;
911 goto icmd_lconst_lcmp_tail;
914 } /* switch (iptr[2].opc) */
915 } /* if (iptr[2].val.i == 0) */
928 COUNT(count_pcmd_load);
932 COUNT(count_pcmd_load);
936 COUNT(count_pcmd_load);
940 /* pop 0 push 1 load */
947 COUNT(count_load_instruction);
948 i = opcode-ICMD_ILOAD;
949 iptr->op1 = argren[iptr->op1];
950 locals[iptr->op1][i].type = i;
951 LOAD(i, LOCALVAR, iptr->op1);
957 #if defined(__I386__)
958 method_uses_edx = true;
964 COUNT(count_check_null);
965 COUNT(count_check_bound);
966 COUNT(count_pcmd_mem);
967 OP2IAT_1(opcode-ICMD_IALOAD);
973 COUNT(count_check_null);
974 COUNT(count_check_bound);
975 COUNT(count_pcmd_mem);
979 /* pop 0 push 0 iinc */
985 count_store_depth[10]++;
987 count_store_depth[i]++;
992 if ((copy->varkind == LOCALVAR) &&
993 (copy->varnum == iptr->op1)) {
994 copy->varkind = TEMPVAR;
1003 /* pop 1 push 0 store */
1013 i = opcode - ICMD_ISTORE;
1014 locals[iptr->op1][i].type = i;
1019 count_store_length[20]++;
1021 count_store_length[i]++;
1024 count_store_depth[10]++;
1026 count_store_depth[i]++;
1028 copy = curstack->prev;
1031 if ((copy->varkind == LOCALVAR) &&
1032 (copy->varnum == iptr->op1)) {
1033 copy->varkind = TEMPVAR;
1039 if ((new - curstack) == 1) {
1040 curstack->varkind = LOCALVAR;
1041 curstack->varnum = iptr->op1;
1043 STORE(opcode-ICMD_ISTORE);
1051 #if defined(__I386__)
1052 method_uses_edx = true;
1056 COUNT(count_check_null);
1057 COUNT(count_check_bound);
1058 COUNT(count_pcmd_mem);
1059 OP3TIA_0(opcode-ICMD_IASTORE);
1065 COUNT(count_check_null);
1066 COUNT(count_check_bound);
1067 COUNT(count_pcmd_mem);
1069 #if defined(__I386__)
1070 method_uses_edx = true;
1077 #ifdef TYPECHECK_STACK_COMPCAT
1080 if (IS_2_WORD_TYPE(curstack->type))
1081 panic("Illegal instruction: POP on category 2 type");
1092 COUNT(count_pcmd_return);
1093 OP1_0(opcode-ICMD_IRETURN);
1094 superblockend = true;
1098 COUNT(count_check_null);
1102 superblockend = true;
1105 case ICMD_PUTSTATIC:
1106 COUNT(count_pcmd_mem);
1110 /* pop 1 push 0 branch */
1113 case ICMD_IFNONNULL:
1114 COUNT(count_pcmd_bra);
1116 tbptr = block + block_index[iptr->op1];
1118 iptr[0].target = (void *) tbptr;
1120 MARKREACHED(tbptr, copy);
1129 COUNT(count_pcmd_bra);
1130 #ifdef CONDITIONAL_LOADCONST
1132 tbptr = block + b_index;
1133 if ((b_count >= 3) &&
1134 ((b_index + 2) == block_index[iptr[0].op1]) &&
1135 (tbptr[1].pre_count == 1) &&
1136 (iptr[1].opc == ICMD_ICONST) &&
1137 (iptr[2].opc == ICMD_GOTO) &&
1138 ((b_index + 3) == block_index[iptr[2].op1]) &&
1139 (tbptr[2].pre_count == 1) &&
1140 (iptr[3].opc == ICMD_ICONST)) {
1141 OP1_1(TYPE_INT, TYPE_INT);
1142 switch (iptr[0].opc) {
1144 iptr[0].opc = ICMD_IFNE_ICONST;
1147 iptr[0].opc = ICMD_IFEQ_ICONST;
1150 iptr[0].opc = ICMD_IFGE_ICONST;
1153 iptr[0].opc = ICMD_IFLT_ICONST;
1156 iptr[0].opc = ICMD_IFLE_ICONST;
1159 iptr[0].opc = ICMD_IFGT_ICONST;
1162 iptr[0].val.i = iptr[1].val.i;
1163 iptr[1].opc = ICMD_ELSE_ICONST;
1164 iptr[1].val.i = iptr[3].val.i;
1165 iptr[2].opc = ICMD_NOP;
1166 iptr[3].opc = ICMD_NOP;
1167 tbptr[1].flags = BBDELETED;
1168 tbptr[2].flags = BBDELETED;
1169 tbptr[1].icount = 0;
1170 tbptr[2].icount = 0;
1171 if (tbptr[3].pre_count == 2) {
1172 len += tbptr[3].icount + 3;
1173 bptr->icount += tbptr[3].icount + 3;
1174 tbptr[3].flags = BBDELETED;
1175 tbptr[3].icount = 0;
1188 tbptr = block + block_index[iptr->op1];
1190 iptr[0].target = (void *) tbptr;
1192 MARKREACHED(tbptr, copy);
1195 /* pop 0 push 0 branch */
1198 COUNT(count_pcmd_bra);
1199 tbptr = block + block_index[iptr->op1];
1201 iptr[0].target = (void *) tbptr;
1203 MARKREACHED(tbptr, copy);
1205 superblockend = true;
1208 /* pop 1 push 0 table branch */
1210 case ICMD_TABLESWITCH:
1211 COUNT(count_pcmd_table);
1213 s4ptr = iptr->val.a;
1214 tbptr = block + block_index[*s4ptr++]; /* default */
1215 MARKREACHED(tbptr, copy);
1216 i = *s4ptr++; /* low */
1217 i = *s4ptr++ - i + 1; /* high */
1219 tptr = DMNEW(void*, i+1);
1220 iptr->target = (void *) tptr;
1222 tptr[0] = (void *) tbptr;
1226 tbptr = block + block_index[*s4ptr++];
1228 tptr[0] = (void *) tbptr;
1231 MARKREACHED(tbptr, copy);
1234 superblockend = true;
1237 /* pop 1 push 0 table branch */
1239 case ICMD_LOOKUPSWITCH:
1240 COUNT(count_pcmd_table);
1242 s4ptr = iptr->val.a;
1243 tbptr = block + block_index[*s4ptr++]; /* default */
1244 MARKREACHED(tbptr, copy);
1245 i = *s4ptr++; /* count */
1247 tptr = DMNEW(void*, i+1);
1248 iptr->target = (void *) tptr;
1250 tptr[0] = (void *) tbptr;
1254 tbptr = block + block_index[s4ptr[1]];
1256 tptr[0] = (void *) tbptr;
1259 MARKREACHED(tbptr, copy);
1263 superblockend = true;
1266 case ICMD_NULLCHECKPOP:
1267 case ICMD_MONITORENTER:
1268 COUNT(count_check_null);
1269 case ICMD_MONITOREXIT:
1273 /* pop 2 push 0 branch */
1275 case ICMD_IF_ICMPEQ:
1276 case ICMD_IF_ICMPNE:
1277 case ICMD_IF_ICMPLT:
1278 case ICMD_IF_ICMPGE:
1279 case ICMD_IF_ICMPGT:
1280 case ICMD_IF_ICMPLE:
1281 COUNT(count_pcmd_bra);
1283 tbptr = block + block_index[iptr->op1];
1285 iptr[0].target = (void *) tbptr;
1287 MARKREACHED(tbptr, copy);
1290 case ICMD_IF_ACMPEQ:
1291 case ICMD_IF_ACMPNE:
1292 COUNT(count_pcmd_bra);
1294 tbptr = block + block_index[iptr->op1];
1296 iptr[0].target = (void *) tbptr;
1298 MARKREACHED(tbptr, copy);
1304 COUNT(count_check_null);
1305 COUNT(count_pcmd_mem);
1306 OPTT2_0(iptr->op1,TYPE_ADR);
1311 if (! IS_2_WORD_TYPE(curstack->type)) {
1313 #ifdef TYPECHECK_STACK_COMPCAT
1316 if (IS_2_WORD_TYPE(curstack->prev->type))
1317 panic("Illegal instruction: POP2 on cat2, cat1 types");
1320 OP1_0ANY; /* second pop */
1323 iptr->opc = ICMD_POP;
1327 /* pop 0 push 1 dup */
1330 #ifdef TYPECHECK_STACK_COMPCAT
1333 if (IS_2_WORD_TYPE(curstack->type))
1334 panic("Illegal instruction: DUP on category 2 type");
1337 COUNT(count_dup_instruction);
1343 if (IS_2_WORD_TYPE(curstack->type)) {
1345 iptr->opc = ICMD_DUP;
1350 /* ..., ????, cat1 */
1351 #ifdef TYPECHECK_STACK_COMPCAT
1353 if (IS_2_WORD_TYPE(curstack->prev->type))
1354 panic("Illegal instruction: DUP2 on cat2, cat1 types");
1358 NEWSTACK(copy->prev->type, copy->prev->varkind,
1359 copy->prev->varnum);
1360 NEWSTACK(copy->type, copy->varkind,
1367 /* pop 2 push 3 dup */
1370 #ifdef TYPECHECK_STACK_COMPCAT
1373 if (IS_2_WORD_TYPE(curstack->type) ||
1374 IS_2_WORD_TYPE(curstack->prev->type))
1375 panic("Illegal instruction: DUP_X1 on cat 2 type");
1383 if (IS_2_WORD_TYPE(curstack->type)) {
1384 /* ..., ????, cat2 */
1385 #ifdef TYPECHECK_STACK_COMPCAT
1387 if (IS_2_WORD_TYPE(curstack->prev->type))
1388 panic("Illegal instruction: DUP2_X1 on cat2, cat2 types");
1391 iptr->opc = ICMD_DUP_X1;
1395 /* ..., ????, cat1 */
1396 #ifdef TYPECHECK_STACK_COMPCAT
1399 if (IS_2_WORD_TYPE(curstack->prev->type)
1400 || IS_2_WORD_TYPE(curstack->prev->prev->type))
1401 panic("Illegal instruction: DUP2_X1 on invalid types");
1408 /* pop 3 push 4 dup */
1412 if (IS_2_WORD_TYPE(curstack->prev->type)) {
1413 /* ..., cat2, ???? */
1414 #ifdef TYPECHECK_STACK_COMPCAT
1416 if (IS_2_WORD_TYPE(curstack->type))
1417 panic("Illegal instruction: DUP_X2 on cat2, cat2 types");
1420 iptr->opc = ICMD_DUP_X1;
1424 /* ..., cat1, ???? */
1425 #ifdef TYPECHECK_STACK_COMPCAT
1428 if (IS_2_WORD_TYPE(curstack->type)
1429 || IS_2_WORD_TYPE(curstack->prev->prev->type))
1430 panic("Illegal instruction: DUP_X2 on invalid types");
1439 if (IS_2_WORD_TYPE(curstack->type)) {
1440 /* ..., ????, cat2 */
1441 if (IS_2_WORD_TYPE(curstack->prev->type)) {
1442 /* ..., cat2, cat2 */
1443 iptr->opc = ICMD_DUP_X1;
1447 /* ..., cat1, cat2 */
1448 #ifdef TYPECHECK_STACK_COMPCAT
1451 if (IS_2_WORD_TYPE(curstack->prev->prev->type))
1452 panic("Illegal instruction: DUP2_X2 on invalid types");
1455 iptr->opc = ICMD_DUP_X2;
1461 /* ..., ????, ????, cat1 */
1462 if (IS_2_WORD_TYPE(curstack->prev->prev->type)) {
1463 /* ..., cat2, ????, cat1 */
1464 #ifdef TYPECHECK_STACK_COMPCAT
1466 if (IS_2_WORD_TYPE(curstack->prev->type))
1467 panic("Illegal instruction: DUP2_X2 on invalid types");
1470 iptr->opc = ICMD_DUP2_X1;
1474 /* ..., cat1, ????, cat1 */
1475 #ifdef TYPECHECK_STACK_COMPCAT
1478 if (IS_2_WORD_TYPE(curstack->prev->type)
1479 || IS_2_WORD_TYPE(curstack->prev->prev->prev->type))
1480 panic("Illegal instruction: DUP2_X2 on invalid types");
1488 /* pop 2 push 2 swap */
1491 #ifdef TYPECHECK_STACK_COMPCAT
1494 if (IS_2_WORD_TYPE(curstack->type)
1495 || IS_2_WORD_TYPE(curstack->prev->type))
1496 panic("Illegal instruction: SWAP on category 2 type");
1505 #if !SUPPORT_DIVISION
1506 iptr[0].opc = ICMD_BUILTIN2;
1507 iptr[0].op1 = TYPE_INT;
1508 iptr[0].val.a = BUILTIN_idiv;
1509 isleafmethod = false;
1514 #if !SUPPORT_DIVISION
1515 iptr[0].opc = ICMD_BUILTIN2;
1516 iptr[0].op1 = TYPE_INT;
1517 iptr[0].val.a = BUILTIN_irem;
1518 isleafmethod = false;
1521 #if defined(__I386__)
1522 method_uses_edx = true;
1528 #if defined(__I386__)
1529 method_uses_ecx = true;
1537 COUNT(count_pcmd_op);
1542 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1543 iptr[0].opc = ICMD_BUILTIN2;
1544 iptr[0].op1 = TYPE_LNG;
1545 iptr[0].val.a = BUILTIN_ldiv;
1546 isleafmethod = false;
1551 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1552 iptr[0].opc = ICMD_BUILTIN2;
1553 iptr[0].op1 = TYPE_LNG;
1554 iptr[0].val.a = BUILTIN_lrem;
1555 isleafmethod = false;
1560 #if defined(__I386__)
1561 method_uses_edx = true;
1568 /* DEBUG */ /*dolog("OP2_1(TYPE_LNG)"); */
1569 COUNT(count_pcmd_op);
1576 COUNT(count_pcmd_op);
1578 #if defined(__I386__)
1579 method_uses_ecx = true;
1580 method_uses_edx = true;
1589 COUNT(count_pcmd_op);
1598 COUNT(count_pcmd_op);
1603 COUNT(count_pcmd_op);
1604 #if !defined(NOLONG_CONDITIONAL)
1605 if ((len > 0) && (iptr[1].val.i == 0)) {
1606 switch (iptr[1].opc) {
1608 iptr[0].opc = ICMD_IF_LCMPEQ;
1610 iptr[0].op1 = iptr[1].op1;
1613 /* iptr[1].opc = ICMD_NOP; */
1615 tbptr = block + block_index[iptr->op1];
1617 iptr[0].target = (void *) tbptr;
1619 MARKREACHED(tbptr, copy);
1620 COUNT(count_pcmd_bra);
1623 iptr[0].opc = ICMD_IF_LCMPNE;
1624 goto icmd_lcmp_if_tail;
1626 iptr[0].opc = ICMD_IF_LCMPLT;
1627 goto icmd_lcmp_if_tail;
1629 iptr[0].opc = ICMD_IF_LCMPGT;
1630 goto icmd_lcmp_if_tail;
1632 iptr[0].opc = ICMD_IF_LCMPLE;
1633 goto icmd_lcmp_if_tail;
1635 iptr[0].opc = ICMD_IF_LCMPGE;
1636 goto icmd_lcmp_if_tail;
1638 OPTT2_1(TYPE_LNG, TYPE_INT);
1643 OPTT2_1(TYPE_LNG, TYPE_INT);
1647 COUNT(count_pcmd_op);
1648 OPTT2_1(TYPE_FLT, TYPE_INT);
1652 COUNT(count_pcmd_op);
1653 OPTT2_1(TYPE_DBL, TYPE_INT);
1661 case ICMD_INT2SHORT:
1662 COUNT(count_pcmd_op);
1663 OP1_1(TYPE_INT, TYPE_INT);
1666 COUNT(count_pcmd_op);
1667 OP1_1(TYPE_LNG, TYPE_LNG);
1670 COUNT(count_pcmd_op);
1671 OP1_1(TYPE_FLT, TYPE_FLT);
1674 COUNT(count_pcmd_op);
1675 OP1_1(TYPE_DBL, TYPE_DBL);
1679 COUNT(count_pcmd_op);
1680 OP1_1(TYPE_INT, TYPE_LNG);
1681 #if defined(__I386__)
1682 method_uses_edx = true;
1686 COUNT(count_pcmd_op);
1687 OP1_1(TYPE_INT, TYPE_FLT);
1690 COUNT(count_pcmd_op);
1691 OP1_1(TYPE_INT, TYPE_DBL);
1694 COUNT(count_pcmd_op);
1695 OP1_1(TYPE_LNG, TYPE_INT);
1698 COUNT(count_pcmd_op);
1699 OP1_1(TYPE_LNG, TYPE_FLT);
1702 COUNT(count_pcmd_op);
1703 OP1_1(TYPE_LNG, TYPE_DBL);
1706 COUNT(count_pcmd_op);
1707 OP1_1(TYPE_FLT, TYPE_INT);
1710 COUNT(count_pcmd_op);
1711 OP1_1(TYPE_FLT, TYPE_LNG);
1712 #if defined(__I386__)
1713 method_uses_edx = true;
1717 COUNT(count_pcmd_op);
1718 OP1_1(TYPE_FLT, TYPE_DBL);
1721 COUNT(count_pcmd_op);
1722 OP1_1(TYPE_DBL, TYPE_INT);
1725 COUNT(count_pcmd_op);
1726 OP1_1(TYPE_DBL, TYPE_LNG);
1727 #if defined(__I386__)
1728 method_uses_edx = true;
1732 COUNT(count_pcmd_op);
1733 OP1_1(TYPE_DBL, TYPE_FLT);
1736 case ICMD_CHECKCAST:
1737 OP1_1(TYPE_ADR, TYPE_ADR);
1738 #if defined(__I386__)
1739 method_uses_edx = true;
1743 case ICMD_INSTANCEOF:
1744 #if defined(__I386__)
1745 method_uses_edx = true;
1747 case ICMD_ARRAYLENGTH:
1748 OP1_1(TYPE_ADR, TYPE_INT);
1752 case ICMD_ANEWARRAY:
1753 OP1_1(TYPE_INT, TYPE_ADR);
1757 COUNT(count_check_null);
1758 COUNT(count_pcmd_mem);
1759 OP1_1(TYPE_ADR, iptr->op1);
1764 case ICMD_GETSTATIC:
1765 COUNT(count_pcmd_mem);
1775 tbptr = block + block_index[iptr->op1];
1777 iptr[0].target = (void *) tbptr;
1779 /* This is a dirty hack. The typechecker
1780 * needs it because the OP1_0ANY below
1781 * overwrites iptr->dst.
1783 iptr->val.a = (void *) iptr->dst;
1785 tbptr->type = BBTYPE_SBR;
1787 /* We need to check for overflow right here because
1788 * the pushed value is poped after MARKREACHED. */
1790 MARKREACHED(tbptr, copy);
1794 /* pop many push any */
1796 case ICMD_INVOKEVIRTUAL:
1797 case ICMD_INVOKESPECIAL:
1798 case ICMD_INVOKEINTERFACE:
1799 case ICMD_INVOKESTATIC:
1800 COUNT(count_pcmd_met);
1802 methodinfo *m = iptr->val.a;
1803 if (m->flags & ACC_STATIC)
1804 {COUNT(count_check_null);}
1806 if (i > arguments_num)
1809 #if defined(__X86_64__)
1817 (IS_FLT_DBL_TYPE(copy->type)) ? farg++ : iarg++;
1821 stackargs += (iarg < intreg_argnum) ? 0 : (iarg - intreg_argnum);
1822 stackargs += (farg < fltreg_argnum) ? 0 : (farg - fltreg_argnum);
1827 if (!(copy->flags & SAVEDVAR)) {
1828 copy->varkind = ARGVAR;
1829 if (IS_FLT_DBL_TYPE(copy->type)) {
1830 if (--farg < fltreg_argnum) {
1831 copy->varnum = farg;
1833 copy->varnum = --stackargs + intreg_argnum;
1836 if (--iarg < intreg_argnum) {
1837 copy->varnum = iarg;
1839 copy->varnum = --stackargs + intreg_argnum;
1843 (IS_FLT_DBL_TYPE(copy->type)) ? --farg : --iarg;
1851 if (! (copy->flags & SAVEDVAR)) {
1852 copy->varkind = ARGVAR;
1859 copy->flags |= SAVEDVAR;
1864 if (m->returntype != TYPE_VOID) {
1865 OP0_1(m->returntype);
1871 /* DEBUG */ /*dolog("builtin3");*/
1873 if (! (curstack->flags & SAVEDVAR)) {
1874 curstack->varkind = ARGVAR;
1875 curstack->varnum = 2;
1877 if (3 > arguments_num) {
1885 /* DEBUG */ /*dolog("builtin2");*/
1886 if (!(curstack->flags & SAVEDVAR)) {
1887 curstack->varkind = ARGVAR;
1888 curstack->varnum = 1;
1890 if (2 > arguments_num) {
1898 /* DEBUG */ /*dolog("builtin1");*/
1899 if (!(curstack->flags & SAVEDVAR)) {
1900 curstack->varkind = ARGVAR;
1901 curstack->varnum = 0;
1903 if (1 > arguments_num) {
1909 copy->flags |= SAVEDVAR;
1912 if (iptr->op1 != TYPE_VOID)
1916 case ICMD_MULTIANEWARRAY:
1919 if ((i + intreg_argnum) > arguments_num)
1920 arguments_num = i + intreg_argnum;
1923 /* check INT type here? Currently typecheck does this. */
1924 if (! (copy->flags & SAVEDVAR)) {
1925 copy->varkind = ARGVAR;
1926 copy->varnum = i + intreg_argnum;
1931 copy->flags |= SAVEDVAR;
1939 case ICMD_CLEAR_ARGREN:
1940 for (i = iptr->op1; i<maxlocals; i++)
1942 iptr->opc = opcode = ICMD_NOP;
1946 case ICMD_READONLY_ARG:
1947 case ICMD_READONLY_ARG+1:
1948 case ICMD_READONLY_ARG+2:
1949 case ICMD_READONLY_ARG+3:
1950 case ICMD_READONLY_ARG+4:
1953 if (curstack->varkind == LOCALVAR) {
1954 i = curstack->varnum;
1955 argren[iptr->op1] = i;
1958 opcode = iptr->opc = opcode - ICMD_READONLY_ARG + ICMD_ISTORE;
1964 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1965 panic("Missing ICMD code during stack analysis");
1970 /* DEBUG */ /*dolog("iptr++");*/
1972 } /* while instructions */
1973 bptr->outstack = curstack;
1974 bptr->outdepth = stackdepth;
1978 superblockend = true;
1980 } /* while blocks */
1981 } while (repeat && !deadcode);
1984 if (block_count > count_max_basic_blocks)
1985 count_max_basic_blocks = block_count;
1986 count_basic_blocks += block_count;
1987 if (instr_count > count_max_javainstr)
1988 count_max_javainstr = instr_count;
1989 count_javainstr += instr_count;
1990 if (stack_count > count_upper_bound_new_stack)
1991 count_upper_bound_new_stack = stack_count;
1992 if ((new - stack) > count_max_new_stack)
1993 count_max_new_stack = (new - stack);
1995 b_count = block_count;
1997 while (--b_count >= 0) {
1998 if (bptr->flags > BBREACHED) {
1999 if (bptr->indepth >= 10)
2000 count_block_stack[10]++;
2002 count_block_stack[bptr->indepth]++;
2005 count_block_size_distribution[len]++;
2007 count_block_size_distribution[10]++;
2009 count_block_size_distribution[11]++;
2011 count_block_size_distribution[12]++;
2013 count_block_size_distribution[13]++;
2015 count_block_size_distribution[14]++;
2017 count_block_size_distribution[15]++;
2019 count_block_size_distribution[16]++;
2021 count_block_size_distribution[17]++;
2027 count_analyse_iterations[0]++;
2028 else if (loops == 2)
2029 count_analyse_iterations[1]++;
2030 else if (loops == 3)
2031 count_analyse_iterations[2]++;
2032 else if (loops == 4)
2033 count_analyse_iterations[3]++;
2035 count_analyse_iterations[4]++;
2037 if (block_count <= 5)
2038 count_method_bb_distribution[0]++;
2039 else if (block_count <= 10)
2040 count_method_bb_distribution[1]++;
2041 else if (block_count <= 15)
2042 count_method_bb_distribution[2]++;
2043 else if (block_count <= 20)
2044 count_method_bb_distribution[3]++;
2045 else if (block_count <= 30)
2046 count_method_bb_distribution[4]++;
2047 else if (block_count <= 40)
2048 count_method_bb_distribution[5]++;
2049 else if (block_count <= 50)
2050 count_method_bb_distribution[6]++;
2051 else if (block_count <= 75)
2052 count_method_bb_distribution[7]++;
2054 count_method_bb_distribution[8]++;
2059 /**********************************************************************/
2060 /* DEBUGGING HELPERS */
2061 /**********************************************************************/
2063 void icmd_print_stack(stackptr s)
2080 /* DEBUG */ /*printf("(%d,%d,%d,%d)",s->varkind,s->flags,s->regoff,s->varnum); fflush(stdout);*/
2081 if (s->flags & SAVEDVAR)
2082 switch (s->varkind) {
2084 if (s->flags & INMEMORY)
2085 printf((regs_ok) ? " M%02d" : " M??", s->regoff);
2086 else if ((s->type == TYPE_FLT) || (s->type == TYPE_DBL))
2087 printf((regs_ok) ? " F%02d" : " F??", s->regoff);
2089 if (regs_ok) printf(" %3s",regs[s->regoff]); else printf(" ???");
2093 printf(" I%02d", s->varnum);
2096 printf(" L%02d", s->varnum);
2099 printf(" A%02d", s->varnum);
2102 printf(" !%02d", j);
2105 switch (s->varkind) {
2107 if (s->flags & INMEMORY)
2108 printf((regs_ok) ? " m%02d" : " m??", s->regoff);
2109 else if ((s->type == TYPE_FLT) || (s->type == TYPE_DBL))
2110 printf((regs_ok) ? " f%02d" : " f??", s->regoff);
2112 if (regs_ok) printf(" %3s",regs[s->regoff]); else printf(" ???");
2116 printf(" i%02d", s->varnum);
2119 printf(" l%02d", s->varnum);
2122 printf(" a%02d", s->varnum);
2125 printf(" ?%02d", j);
2133 static void print_reg(stackptr s) {
2135 if (s->flags & SAVEDVAR)
2136 switch (s->varkind) {
2138 if (s->flags & INMEMORY)
2139 printf(" tm%02d", s->regoff);
2141 printf(" tr%02d", s->regoff);
2144 printf(" s %02d", s->varnum);
2147 printf(" l %02d", s->varnum);
2150 printf(" a %02d", s->varnum);
2153 printf(" ! %02d", s->varnum);
2156 switch (s->varkind) {
2158 if (s->flags & INMEMORY)
2159 printf(" Tm%02d", s->regoff);
2161 printf(" Tr%02d", s->regoff);
2164 printf(" S %02d", s->varnum);
2167 printf(" L %02d", s->varnum);
2170 printf(" A %02d", s->varnum);
2173 printf(" ? %02d", s->varnum);
2183 char *icmd_builtin_name(functionptr bptr)
2185 builtin_descriptor *bdesc = builtin_desc;
2186 while ((bdesc->opcode != 0) && (bdesc->builtin != bptr))
2188 return (bdesc->opcode) ? bdesc->name : "<NOT IN TABLE>";
2192 static char *jit_type[] = {
2201 void show_icmd_method()
2204 s4 *s4ptr; /* used */
2209 utf_fprint(stdout, class->name);
2211 utf_fprint(stdout, method->name);
2213 utf_fprint(stdout, method->descriptor);
2214 printf ("\n\nMax locals: %d\n", (int) maxlocals);
2215 printf ("Max stack: %d\n", (int) maxstack);
2217 printf ("Line number table length: %d\n",method->linenumbercount);
2219 printf ("Exceptions (Number: %d):\n", exceptiontablelength);
2220 for (ex = extable; ex != NULL; ex = ex->down) {
2221 printf(" L%03d ... ", ex->start->debug_nr );
2222 printf("L%03d = ", ex->end->debug_nr);
2223 printf("L%03d\n", ex->handler->debug_nr);
2226 printf ("Local Table:\n");
2227 for (i = 0; i < maxlocals; i++) {
2228 printf(" %3d: ", i);
2229 for (j = TYPE_INT; j <= TYPE_ADR; j++)
2230 if (locals[i][j].type >= 0) {
2231 printf(" (%s) ", jit_type[j]);
2232 if (locals[i][j].flags & INMEMORY)
2233 printf((regs_ok) ? "m%2d" : "m??", locals[i][j].regoff);
2234 else if ((j == TYPE_FLT) || (j == TYPE_DBL))
2235 printf((regs_ok) ? "f%02d" : "f??", locals[i][j].regoff);
2237 if (regs_ok) printf("%3s",regs[locals[i][j].regoff]); else printf("???");
2244 printf ("Interface Table:\n");
2245 for (i = 0; i < maxstack; i++) {
2246 if ((interfaces[i][0].type >= 0) || (interfaces[i][1].type >= 0) ||
2247 (interfaces[i][2].type >= 0) || (interfaces[i][3].type >= 0) ||
2248 (interfaces[i][4].type >= 0)) {
2249 printf(" %3d: ", i);
2250 for (j = TYPE_INT; j <= TYPE_ADR; j++)
2251 if (interfaces[i][j].type >= 0) {
2252 printf(" (%s) ", jit_type[j]);
2253 if (interfaces[i][j].flags & SAVEDVAR) {
2254 if (interfaces[i][j].flags & INMEMORY)
2255 printf((regs_ok) ? "M%2d" : "M??", interfaces[i][j].regoff);
2256 else if ((j == TYPE_FLT) || (j == TYPE_DBL))
2257 printf((regs_ok) ? "F%02d" : "F??", interfaces[i][j].regoff);
2259 if (regs_ok) printf("%3s",regs[interfaces[i][j].regoff]); else printf("???");
2263 if (interfaces[i][j].flags & INMEMORY)
2264 printf((regs_ok) ? "m%2d" : "m??", interfaces[i][j].regoff);
2265 else if ((j == TYPE_FLT) || (j == TYPE_DBL))
2266 printf((regs_ok) ? "f%02d" : "f??", interfaces[i][j].regoff);
2268 if (regs_ok) printf("%3s",regs[interfaces[i][j].regoff]); else printf("???");
2277 if (showdisassemble) {
2278 #if defined(__I386__) || defined(__X86_64__)
2282 u1ptr = method->mcode + dseglen;
2283 for (i = 0; i < block[0].mpc; i++, u1ptr++) {
2284 a = disassinstr(u1ptr, i);
2290 s4ptr = (s4 *) (method->mcode + dseglen);
2291 for (i = 0; i < block[0].mpc; i += 4, s4ptr++) {
2292 disassinstr(*s4ptr, i);
2299 for (bptr = block; bptr != NULL; bptr = bptr->next) {
2300 show_icmd_block(bptr);
2305 void show_icmd_block(basicblock *bptr)
2309 s4 *s4ptr; /* used */
2312 if (bptr->flags != BBDELETED) {
2313 deadcode = bptr->flags <= BBREACHED;
2316 for (j = method->maxstack; j > 0; j--)
2319 icmd_print_stack(bptr->instack);
2320 printf("] L%03d(%d - %d) flags=%d:\n", bptr->debug_nr, bptr->icount, bptr->pre_count,bptr->flags);
2321 iptr = bptr->iinstr;
2323 for (i=0; i < bptr->icount; i++, iptr++) {
2326 for (j = method->maxstack; j > 0; j--)
2330 icmd_print_stack(iptr->dst);
2331 printf("] %4d ", i);
2332 /* DEBUG */ /*fflush(stdout);*/
2333 show_icmd(iptr,deadcode);
2337 if (showdisassemble && (!deadcode)) {
2338 #if defined(__I386__) || defined(__X86_64__)
2344 u1ptr = method->mcode + dseglen + i;
2346 if (bptr->next != NULL) {
2347 for (; i < bptr->next->mpc; i++, u1ptr++) {
2348 a = disassinstr(u1ptr, i);
2355 for (; u1ptr < (u1 *) (method->mcode + method->mcodelength); i++, u1ptr++) {
2356 a = disassinstr(u1ptr, i);
2365 s4ptr = (s4 *) (method->mcode + dseglen + i);
2367 if (bptr->next != NULL) {
2368 for (; i < bptr->next->mpc; i += 4, s4ptr++) {
2369 disassinstr(*s4ptr, i);
2374 for (; s4ptr < (s4 *) (method->mcode + method->mcodelength); i += 4, s4ptr++) {
2375 disassinstr(*s4ptr, i);
2385 void show_icmd(instruction *iptr,bool deadcode)
2391 printf("%s", icmd_names[iptr->opc]);
2393 switch ((int) iptr->opc) {
2394 case ICMD_IADDCONST:
2395 case ICMD_ISUBCONST:
2396 case ICMD_IMULCONST:
2399 case ICMD_IREM0X10001:
2400 case ICMD_IANDCONST:
2402 case ICMD_IXORCONST:
2403 case ICMD_ISHLCONST:
2404 case ICMD_ISHRCONST:
2405 case ICMD_IUSHRCONST:
2406 case ICMD_LSHLCONST:
2407 case ICMD_LSHRCONST:
2408 case ICMD_LUSHRCONST:
2410 case ICMD_ELSE_ICONST:
2411 case ICMD_IFEQ_ICONST:
2412 case ICMD_IFNE_ICONST:
2413 case ICMD_IFLT_ICONST:
2414 case ICMD_IFGE_ICONST:
2415 case ICMD_IFGT_ICONST:
2416 case ICMD_IFLE_ICONST:
2417 printf(" %d", iptr->val.i);
2420 case ICMD_LADDCONST:
2421 case ICMD_LSUBCONST:
2422 case ICMD_LMULCONST:
2425 case ICMD_LANDCONST:
2427 case ICMD_LXORCONST:
2429 #if defined(__I386__)
2430 printf(" %lld", iptr->val.l);
2432 printf(" %ld", iptr->val.l);
2437 printf(" %f", iptr->val.f);
2441 printf(" %f", iptr->val.d);
2445 printf(" %p", iptr->val.a);
2450 printf(" %d,", ((fieldinfo *) iptr->val.a)->offset);
2451 case ICMD_PUTSTATIC:
2452 case ICMD_GETSTATIC:
2454 utf_fprint(stdout, ((fieldinfo *) iptr->val.a)->class->name);
2456 utf_fprint(stdout, ((fieldinfo *) iptr->val.a)->name);
2458 utf_fprint(stdout, ((fieldinfo *) iptr->val.a)->descriptor);
2463 printf(" %d + %d", iptr->op1, iptr->val.i);
2498 printf(" %d", iptr->op1);
2504 ((classinfo *) iptr->val.a)->name);
2508 switch (iptr->op1) {
2536 case ICMD_ANEWARRAY:
2540 ((classinfo *) iptr->val.a)->name);
2544 case ICMD_MULTIANEWARRAY:
2547 printf(" %d ",iptr->op1);
2548 vft = (vftbl *)iptr->val.a;
2550 utf_fprint(stdout,vft->class->name);
2556 case ICMD_CHECKCAST:
2557 case ICMD_INSTANCEOF:
2559 classinfo *c = iptr->val.a;
2560 if (c->flags & ACC_INTERFACE)
2561 printf(" (INTERFACE) ");
2563 printf(" (CLASS,%3d) ", c->vftbl->diffval);
2564 utf_fprint(stdout, c->name);
2571 printf(" %s", icmd_builtin_name((functionptr) iptr->val.a));
2574 case ICMD_INVOKEVIRTUAL:
2575 case ICMD_INVOKESPECIAL:
2576 case ICMD_INVOKESTATIC:
2577 case ICMD_INVOKEINTERFACE:
2580 ((methodinfo *) iptr->val.a)->class->name);
2583 ((methodinfo *) iptr->val.a)->name);
2592 if (deadcode || !iptr->target)
2593 printf("(%d) op1=%d", iptr->val.i, iptr->op1);
2595 printf("(%d) L%03d", iptr->val.i, ((basicblock *) iptr->target)->debug_nr);
2604 if (deadcode || !iptr->target)
2605 printf("(%lld) op1=%d", iptr->val.l, iptr->op1);
2607 printf("(%lld) L%03d", iptr->val.l, ((basicblock *) iptr->target)->debug_nr);
2613 case ICMD_IFNONNULL:
2614 case ICMD_IF_ICMPEQ:
2615 case ICMD_IF_ICMPNE:
2616 case ICMD_IF_ICMPLT:
2617 case ICMD_IF_ICMPGE:
2618 case ICMD_IF_ICMPGT:
2619 case ICMD_IF_ICMPLE:
2620 case ICMD_IF_LCMPEQ:
2621 case ICMD_IF_LCMPNE:
2622 case ICMD_IF_LCMPLT:
2623 case ICMD_IF_LCMPGE:
2624 case ICMD_IF_LCMPGT:
2625 case ICMD_IF_LCMPLE:
2626 case ICMD_IF_ACMPEQ:
2627 case ICMD_IF_ACMPNE:
2628 if (deadcode || !iptr->target)
2629 printf(" op1=%d", iptr->op1);
2631 printf(" L%03d", ((basicblock *) iptr->target)->debug_nr);
2634 case ICMD_TABLESWITCH:
2635 s4ptr = (s4*)iptr->val.a;
2637 if (deadcode || !iptr->target) {
2638 printf(" %d;", *s4ptr);
2641 tptr = (void **) iptr->target;
2642 printf(" L%03d;", ((basicblock *) *tptr)->debug_nr);
2646 s4ptr++; /* skip default */
2647 j = *s4ptr++; /* low */
2648 j = *s4ptr++ - j; /* high */
2650 if (deadcode || !*tptr)
2651 printf(" %d", *s4ptr++);
2653 printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
2660 case ICMD_LOOKUPSWITCH:
2661 s4ptr = (s4*)iptr->val.a;
2663 if (deadcode || !iptr->target) {
2664 printf(" %d;", *s4ptr);
2667 tptr = (void **) iptr->target;
2668 printf(" L%03d;", ((basicblock *) *tptr)->debug_nr);
2671 s4ptr++; /* default */
2672 j = *s4ptr++; /* count */
2675 if (deadcode || !*tptr) {
2676 s4ptr++; /* skip value */
2677 printf(" %d",*s4ptr++);
2680 printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
2686 printf(" Line number: %d, class:",iptr->line);
2687 utf_display(iptr->clazz->name);
2692 * These are local overrides for various environment variables in Emacs.
2693 * Please do not remove this and leave it at the end of the file, where
2694 * Emacs will automagically detect them.
2695 * ---------------------------------------------------------------------
2698 * indent-tabs-mode: t