1 /* src/vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
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: Edwin Steiner
29 Changes: Christian Thalinger
31 $Id: typecheck.c 2966 2005-07-10 11:02:31Z edwin $
39 #include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
41 #ifdef CACAO_TYPECHECK
44 #include "mm/memory.h"
45 #include "toolbox/logging.h"
46 #include "native/native.h"
47 #include "vm/builtin.h"
48 #include "vm/jit/patcher.h"
49 #include "vm/loader.h"
50 #include "vm/options.h"
51 #include "vm/tables.h"
52 #include "vm/jit/jit.h"
53 #include "vm/jit/stack.h"
54 #include "vm/access.h"
55 #include "vm/resolve.h"
58 /****************************************************************************/
60 /****************************************************************************/
62 #ifdef TYPECHECK_DEBUG
63 #define TYPECHECK_ASSERT(cond) assert(cond)
65 #define TYPECHECK_ASSERT(cond)
68 #ifdef TYPECHECK_VERBOSE_OPT
69 bool typecheckverbose = false;
70 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
75 #ifdef TYPECHECK_VERBOSE
76 #define TYPECHECK_VERBOSE_IMPORTANT
77 #define LOG(str) DOLOG(log_text(str))
78 #define LOG1(str,a) DOLOG(dolog(str,a))
79 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
80 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
81 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
83 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
86 #define typevectorset_print(x,y,z)
88 #define LOGFLUSH DOLOG(fflush(get_logfile()))
89 #define LOGNL DOLOG(log_plain("\n"))
90 #define LOGSTR(str) DOLOG(log_plain(str))
91 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
92 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
93 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
94 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
95 #define LOGNAME(c) DOLOG(do {log_plain_utf(IS_CLASSREF(c) ? c.ref->name : c.cls->name);} while(0))
100 #define LOG3(str,a,b,c)
101 #define LOGIF(cond,str)
102 #define LOGINFO(info)
106 #define LOGSTR1(str,a)
107 #define LOGSTR2(str,a,b)
108 #define LOGSTR3(str,a,b,c)
113 #ifdef TYPECHECK_VERBOSE_IMPORTANT
114 #define LOGimp(str) DOLOG(log_text(str))
115 #define LOGimpSTR(str) DOLOG(log_plain(str))
116 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
119 #define LOGimpSTR(str)
120 #define LOGimpSTRu(utf)
123 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
129 typestack_print(FILE *file,stackptr stack)
131 #ifdef TYPEINFO_DEBUG
133 /*fprintf(file,"<%p>",stack);*/
134 typeinfo_print_stacktype(file,stack->type,&(stack->typeinfo));
136 if (stack) fprintf(file," ");
143 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
145 fprintf(file,"Stack: ");
146 typestack_print(file,instack);
147 fprintf(file," Locals:");
148 typevectorset_print(file,localset,size);
153 /****************************************************************************/
155 /****************************************************************************/
157 #ifdef TYPECHECK_DEBUG
158 /*#define TYPECHECK_STATISTICS*/
161 #ifdef TYPECHECK_STATISTICS
162 #define STAT_ITERATIONS 10
163 #define STAT_BLOCKS 10
164 #define STAT_LOCALS 16
166 static int stat_typechecked = 0;
167 static int stat_typechecked_jsr = 0;
168 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
169 static int stat_reached = 0;
170 static int stat_copied = 0;
171 static int stat_merged = 0;
172 static int stat_merging_changed = 0;
173 static int stat_backwards = 0;
174 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
175 static int stat_locals[STAT_LOCALS+1] = { 0 };
176 static int stat_ins = 0;
177 static int stat_ins_field = 0;
178 static int stat_ins_invoke = 0;
179 static int stat_ins_primload = 0;
180 static int stat_ins_aload = 0;
181 static int stat_ins_builtin = 0;
182 static int stat_ins_builtin_gen = 0;
183 static int stat_ins_branch = 0;
184 static int stat_ins_switch = 0;
185 static int stat_ins_unchecked = 0;
186 static int stat_handlers_reached = 0;
187 static int stat_savedstack = 0;
189 #define TYPECHECK_COUNT(cnt) (cnt)++
190 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
191 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
193 if ((val) < (limit)) (array)[val]++; \
194 else (array)[limit]++; \
197 static void print_freq(FILE *file,int *array,int limit)
200 for (i=0; i<limit; ++i)
201 fprintf(file," %3d: %8d\n",i,array[i]);
202 fprintf(file," >=%3d: %8d\n",limit,array[limit]);
205 void typecheck_print_statistics(FILE *file) {
206 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
207 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
208 fprintf(file,"reached blocks : %8d\n",stat_reached);
209 fprintf(file,"copied states : %8d\n",stat_copied);
210 fprintf(file,"merged states : %8d\n",stat_merged);
211 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
212 fprintf(file,"backwards branches : %8d\n",stat_backwards);
213 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
214 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
215 fprintf(file,"instructions : %8d\n",stat_ins);
216 fprintf(file," field access : %8d\n",stat_ins_field);
217 fprintf(file," invocations : %8d\n",stat_ins_invoke);
218 fprintf(file," load primitive : %8d\n",stat_ins_primload);
219 fprintf(file," load address : %8d\n",stat_ins_aload);
220 fprintf(file," builtins : %8d\n",stat_ins_builtin);
221 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
222 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
223 fprintf(file," branches : %8d\n",stat_ins_branch);
224 fprintf(file," switches : %8d\n",stat_ins_switch);
225 fprintf(file,"iterations used:\n");
226 print_freq(file,stat_iterations,STAT_ITERATIONS);
227 fprintf(file,"basic blocks per method / 10:\n");
228 print_freq(file,stat_blocks,STAT_BLOCKS);
229 fprintf(file,"locals:\n");
230 print_freq(file,stat_locals,STAT_LOCALS);
235 #define TYPECHECK_COUNT(cnt)
236 #define TYPECHECK_COUNTIF(cond,cnt)
237 #define TYPECHECK_COUNT_FREQ(array,val,limit)
241 /****************************************************************************/
242 /* MACROS FOR STACK TYPE CHECKING */
243 /****************************************************************************/
245 #define TYPECHECK_VERIFYERROR_ret(m,msg,retval) \
247 *exceptionptr = new_verifyerror((m), (msg)); \
251 #define TYPECHECK_VERIFYERROR_main(msg) TYPECHECK_VERIFYERROR_ret(state.m,(msg),NULL)
252 #define TYPECHECK_VERIFYERROR_bool(msg) TYPECHECK_VERIFYERROR_ret(state->m,(msg),false)
254 #define TYPECHECK_CHECK_TYPE(sp,tp,msg) \
256 if ((sp)->type != (tp)) { \
257 *exceptionptr = new_verifyerror(state->m, (msg)); \
262 #define TYPECHECK_INT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_INT,"Expected to find integer on stack")
263 #define TYPECHECK_LNG(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_LNG,"Expected to find long on stack")
264 #define TYPECHECK_FLT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_FLT,"Expected to find float on stack")
265 #define TYPECHECK_DBL(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_DBL,"Expected to find double on stack")
266 #define TYPECHECK_ADR(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_ADR,"Expected to find object on stack")
268 /****************************************************************************/
269 /* VERIFIER STATE STRUCT */
270 /****************************************************************************/
272 /* verifier_state - This structure keeps the current state of the */
273 /* bytecode verifier for passing it between verifier functions. */
275 typedef struct verifier_state {
276 stackptr curstack; /* input stack top for current instruction */
277 instruction *iptr; /* pointer to current instruction */
278 basicblock *bptr; /* pointer to current basic block */
280 methodinfo *m; /* the current method */
281 codegendata *cd; /* codegendata for current method */
282 registerdata *rd; /* registerdata for current method */
284 s4 numlocals; /* number of local variables */
285 s4 validlocals; /* number of Java-accessible locals */
286 void *localbuf; /* local variable types for each block start */
287 typevector *localset; /* typevector set for local variables */
288 typedescriptor returntype; /* return type of the current method */
290 stackptr savedstackbuf; /* buffer for saving the stack */
291 stackptr savedstack; /* saved instack of current block */
293 exceptiontable **handlers; /* active exception handlers */
294 stackelement excstack; /* instack for exception handlers */
296 bool repeat; /* if true, blocks are iterated over again */
297 bool initmethod; /* true if this is an "<init>" method */
298 bool jsrencountered; /* true if we there was a JSR */
301 /****************************************************************************/
302 /* TYPESTACK MACROS AND FUNCTIONS */
304 /* These macros and functions act on the 'type stack', which is a shorthand */
305 /* for the types of the stackslots of the current stack. The type of a */
306 /* stack slot is usually described by a TYPE_* constant and -- for TYPE_ADR */
307 /* -- by the typeinfo of the slot. The only thing that makes the type stack */
308 /* more complicated are returnAddresses of local subroutines, because a */
309 /* single stack slot may contain a set of more than one possible return */
310 /* address. This is handled by 'return address sets'. A return address set */
311 /* is kept as a linked list dangling off the typeinfo of the stack slot. */
312 /****************************************************************************/
314 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
315 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
317 #define TYPESTACK_IS_REFERENCE(sptr) \
318 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
320 #define TYPESTACK_RETURNADDRESSSET(sptr) \
321 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
323 #define RETURNADDRESSSET_SEEK(set,pos) \
324 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
326 #define TYPESTACK_COPY(sp,copy) \
327 do {for(; sp; sp=sp->prev, copy=copy->prev) { \
328 copy->type = sp->type; \
329 TYPEINFO_COPY(sp->typeinfo,copy->typeinfo); \
332 /* typestack_copy **************************************************************
334 Copy the types on the given stack to the destination stack.
336 This function does a straight forward copy except for returnAddress types.
337 For returnAddress slots only the return addresses corresponding to
338 typevectors in the SELECTED set are copied.
341 state............current verifier state
342 y................stack with types to copy
343 selected.........set of selected typevectors
346 *dst.............the destination stack
349 true.............success
350 false............an exception has been thrown
352 *******************************************************************************/
355 typestack_copy(verifier_state *state,stackptr dst,stackptr y,typevector *selected)
358 typeinfo_retaddr_set *sety;
359 typeinfo_retaddr_set *new;
360 typeinfo_retaddr_set **next;
363 for (;dst; dst=dst->prev, y=y->prev) {
365 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
368 if (dst->type != y->type) {
369 *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
372 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
373 if (dst->type == TYPE_ADDRESS) {
374 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
375 /* We copy the returnAddresses from the selected
378 LOG("copying returnAddress");
379 sety = TYPESTACK_RETURNADDRESSSET(y);
381 for (k=0,sel=selected; sel; sel=sel->alt) {
382 LOG1("selected k=%d",sel->k);
387 *next = DNEW(typeinfo_retaddr_set);
388 (*next)->addr = sety->addr;
389 next = &((*next)->alt);
392 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
395 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
400 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
406 /* typestack_put_retaddr *******************************************************
408 Put a returnAddress into a stack slot.
410 The stack slot receives a set of return addresses with as many members as
411 there are typevectors in the local variable set.
414 retaddr..........the returnAddress to set (a basicblock *)
415 loc..............the local variable typevector set
418 *dst.............the destination stack slot
420 *******************************************************************************/
423 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
425 TYPECHECK_ASSERT(dst->type == TYPE_ADDRESS);
427 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
428 for (;loc; loc=loc->alt) {
429 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
431 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
432 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
436 /* typestack_collapse **********************************************************
438 Collapse the given stack by shortening all return address sets to a single
442 *dst.............the destination stack to collapse
444 *******************************************************************************/
447 typestack_collapse(stackptr dst)
449 for (; dst; dst = dst->prev) {
450 if (TYPESTACK_IS_RETURNADDRESS(dst))
451 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
455 /* typestack_merge *************************************************************
457 Merge the types on one stack into the destination stack.
460 state............current state of the verifier
461 dst..............the destination stack
462 y................the second stack
465 *dst.............receives the result of the stack merge
468 typecheck_TRUE...*dst has been modified
469 typecheck_FALSE..*dst has not been modified
470 typecheck_FAIL...an exception has been thrown
472 *******************************************************************************/
474 static typecheck_result
475 typestack_merge(verifier_state *state,stackptr dst,stackptr y)
478 bool changed = false;
480 for (; dst; dst = dst->prev, y=y->prev) {
482 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
483 return typecheck_FAIL;
485 if (dst->type != y->type) {
486 *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
487 return typecheck_FAIL;
489 if (dst->type == TYPE_ADDRESS) {
490 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
491 /* dst has returnAddress type */
492 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
493 *exceptionptr = new_verifyerror(state->m,"Merging returnAddress with reference");
494 return typecheck_FAIL;
498 /* dst has reference type */
499 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
500 *exceptionptr = new_verifyerror(state->m,"Merging reference with returnAddress");
501 return typecheck_FAIL;
503 r = typeinfo_merge(state->m,&(dst->typeinfo),&(y->typeinfo));
504 if (r == typecheck_FAIL)
511 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
512 return typecheck_FAIL;
517 /* typestack_add ***************************************************************
519 Add the return addresses in the given stack at a given k-index to the
520 corresponding return address sets in the destination stack.
523 dst..............the destination stack
524 y................the second stack
525 ky...............the k-index which should be selected from the Y stack
528 *dst.............receives the result of adding the addresses
530 *******************************************************************************/
533 typestack_add(stackptr dst,stackptr y,int ky)
535 typeinfo_retaddr_set *setd;
536 typeinfo_retaddr_set *sety;
538 for (; dst; dst = dst->prev, y=y->prev) {
539 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
540 setd = TYPESTACK_RETURNADDRESSSET(dst);
541 sety = TYPESTACK_RETURNADDRESSSET(y);
542 RETURNADDRESSSET_SEEK(sety,ky);
545 setd->alt = DNEW(typeinfo_retaddr_set);
546 setd->alt->addr = sety->addr;
547 setd->alt->alt = NULL;
552 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
554 typestack_separable_with(stackptr a,stackptr b,int kb)
556 typeinfo_retaddr_set *seta;
557 typeinfo_retaddr_set *setb;
559 for (; a; a = a->prev, b = b->prev) {
561 if (TYPESTACK_IS_RETURNADDRESS(a)) {
562 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
563 seta = TYPESTACK_RETURNADDRESSSET(a);
564 setb = TYPESTACK_RETURNADDRESSSET(b);
565 RETURNADDRESSSET_SEEK(setb,kb);
567 for (;seta;seta=seta->alt)
568 if (seta->addr != setb->addr) return true;
571 TYPECHECK_ASSERT(!b);
575 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
577 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
579 typeinfo_retaddr_set *seta;
580 typeinfo_retaddr_set *setb;
582 for (; a; a = a->prev, b = b->prev) {
584 if (TYPESTACK_IS_RETURNADDRESS(a)) {
585 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
586 seta = TYPESTACK_RETURNADDRESSSET(a);
587 setb = TYPESTACK_RETURNADDRESSSET(b);
588 RETURNADDRESSSET_SEEK(seta,ka);
589 RETURNADDRESSSET_SEEK(setb,kb);
591 if (seta->addr != setb->addr) return true;
594 TYPECHECK_ASSERT(!b);
598 /****************************************************************************/
599 /* TYPESTATE FUNCTIONS */
601 /* These functions act on the 'type state', which comprises: */
602 /* - the types of the stack slots of the current stack */
603 /* - the set of type vectors describing the local variables */
604 /****************************************************************************/
606 /* typestate_merge *************************************************************
608 Merge the types of one state into the destination state.
611 state............current state of the verifier
612 deststack........the destination stack
613 destloc..........the destination set of local variable typevectors
614 ystack...........the second stack
615 yloc.............the second set of local variable typevectors
618 *deststack.......receives the result of the stack merge
619 *destloc.........receives the result of the local variable merge
622 typecheck_TRUE...destination state has been modified
623 typecheck_FALSE..destination state has not been modified
624 typecheck_FAIL...an exception has been thrown
626 *******************************************************************************/
628 static typecheck_result
629 typestate_merge(verifier_state *state,
630 stackptr deststack,typevector *destloc,
631 stackptr ystack,typevector *yloc)
633 typevector *dvec,*yvec;
635 bool changed = false;
639 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
640 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
641 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
642 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,state->numlocals)); LOGNL;
645 /* The stack is always merged. If there are returnAddresses on
646 * the stack they are ignored in this step. */
648 r = typestack_merge(state,deststack,ystack);
649 if (r == typecheck_FAIL)
653 /* If there have not been any JSRs we just have a single typevector merge */
654 if (!state->jsrencountered) {
655 r = typevector_merge(state->m,destloc,yloc,state->numlocals);
656 if (r == typecheck_FAIL)
661 for (yvec=yloc; yvec; yvec=yvec->alt) {
664 /* Check if the typestates (deststack,destloc) will be
665 * separable when (ystack,yvec) is added. */
667 if (!typestack_separable_with(deststack,ystack,ky)
668 && !typevectorset_separable_with(destloc,yvec,state->numlocals))
670 /* No, the resulting set won't be separable, thus we
671 * may merge all states in (deststack,destloc) and
674 typestack_collapse(deststack);
675 if (typevectorset_collapse(state->m,destloc,state->numlocals) == typecheck_FAIL)
676 return typecheck_FAIL;
677 if (typevector_merge(state->m,destloc,yvec,state->numlocals) == typecheck_FAIL)
678 return typecheck_FAIL;
681 /* Yes, the resulting set will be separable. Thus we check
682 * if we may merge (ystack,yvec) with a single state in
683 * (deststack,destloc). */
685 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
686 if (!typestack_separable_from(ystack,ky,deststack,kd)
687 && !typevector_separable_from(yvec,dvec,state->numlocals))
689 /* The typestate (ystack,yvec) is not separable from
690 * (deststack,dvec) by any returnAddress. Thus we may
691 * merge the states. */
693 r = typevector_merge(state->m,dvec,yvec,state->numlocals);
694 if (r == typecheck_FAIL)
702 /* The typestate (ystack,yvec) is separable from all typestates
703 * (deststack,destloc). Thus we must add this state to the
706 typestack_add(deststack,ystack,ky);
707 typevectorset_add(destloc,yvec,state->numlocals);
716 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
717 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
723 /* typestate_reach *************************************************************
725 Reach a destination block and propagate stack and local variable types
728 state............current state of the verifier
729 destblock........destination basic block
730 ystack...........stack to propagate
731 yloc.............set of local variable typevectors to propagate
734 state->repeat....set to true if the verifier must iterate again
735 over the basic blocks
738 true.............success
739 false............an exception has been thrown
741 *******************************************************************************/
744 typestate_reach(verifier_state *state,
745 basicblock *destblock,
746 stackptr ystack,typevector *yloc)
750 bool changed = false;
753 LOG1("reaching block L%03d",destblock->debug_nr);
754 TYPECHECK_COUNT(stat_reached);
756 destidx = destblock - state->cd->method->basicblocks;
757 destloc = MGET_TYPEVECTOR(state->localbuf,destidx,state->numlocals);
759 /* When branching backwards we have to check for uninitialized objects */
761 if (destblock <= state->bptr) {
765 /* XXX FIXME FOR INLINING */
768 TYPECHECK_COUNT(stat_backwards);
770 for (sp = ystack; sp; sp=sp->prev)
771 if (sp->type == TYPE_ADR &&
772 TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
773 /*printf("current: %d, dest: %d\n", state->bptr->debug_nr, destblock->debug_nr);*/
774 *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object on stack");
778 for (i=0; i<state->numlocals; ++i)
779 if (yloc->td[i].type == TYPE_ADR &&
780 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info)) {
781 *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object in local variable");
787 if (destblock->flags == BBTYPECHECK_UNDEF) {
788 /* The destblock has never been reached before */
790 TYPECHECK_COUNT(stat_copied);
791 LOG1("block (index %04d) reached first time",destidx);
793 if (!typestack_copy(state,destblock->instack,ystack,yloc))
795 COPY_TYPEVECTORSET(yloc,destloc,state->numlocals);
799 /* The destblock has already been reached before */
801 TYPECHECK_COUNT(stat_merged);
802 LOG1("block (index %04d) reached before",destidx);
804 r = typestate_merge(state,destblock->instack,destloc,ystack,yloc);
805 if (r == typecheck_FAIL)
808 TYPECHECK_COUNTIF(changed,stat_merging_changed);
813 destblock->flags = BBTYPECHECK_REACHED;
814 if (destblock <= state->bptr) {
816 state->repeat = true;
822 /* typestate_ret ***************************************************************
824 Reach the destinations of a RET instruction.
827 state............current state of the verifier
828 retindex.........index of local variable containing the returnAddress
831 state->repeat....set to true if the verifier must iterate again
832 over the basic blocks
835 true.............success
836 false............an exception has been thrown
838 *******************************************************************************/
841 typestate_ret(verifier_state *state,int retindex)
844 typevector *selected;
845 basicblock *destblock;
847 for (yvec=state->localset; yvec; ) {
848 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex])) {
849 *exceptionptr = new_verifyerror(state->m,"Illegal instruction: RET on non-returnAddress");
853 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
855 selected = typevectorset_select(&yvec,retindex,destblock);
857 if (!typestate_reach(state,destblock,state->curstack,selected))
863 /****************************************************************************/
864 /* MACROS FOR LOCAL VARIABLE CHECKING */
865 /****************************************************************************/
867 #define INDEX_ONEWORD(num) \
868 do { if((num)<0 || (num)>=state->validlocals) \
869 TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
870 #define INDEX_TWOWORD(num) \
871 do { if((num)<0 || ((num)+1)>=state->validlocals) \
872 TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
874 #define STORE_ONEWORD(num,type) \
875 do {typevectorset_store(state->localset,num,type,NULL);} while(0)
877 #define STORE_TWOWORD(num,type) \
878 do {typevectorset_store_twoword(state->localset,num,type);} while(0)
881 #ifdef TYPECHECK_VERBOSE
882 #define WORDCHECKFAULT \
884 dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n", \
885 state->iptr->op1,state->iptr->method->class->name->text, \
886 state->iptr->method->name->text,state->m->class->name->text,state->m->name->text); \
887 show_icmd(state->iptr++, false); \
888 show_icmd(state->iptr, false); \
891 #define WORDCHECKFAULT
895 #define CHECK_ONEWORD(num,tp) \
896 do {TYPECHECK_COUNT(stat_ins_primload); \
897 if (state->jsrencountered) { \
898 if (!typevectorset_checktype(state->localset,num,tp)) { \
900 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
904 if (state->localset->td[num].type != tp) { \
905 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
911 #define CHECK_TWOWORD(num,type) \
912 do {TYPECHECK_COUNT(stat_ins_primload); \
913 if (!typevectorset_checktype(state->localset,num,type)) { \
915 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
920 /****************************************************************************/
922 /****************************************************************************/
924 #define COPYTYPE(source,dest) \
925 {if ((source)->type == TYPE_ADR) \
926 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
928 #define ISBUILTIN(v) (bte->fp == (functionptr) (v))
930 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
932 * class........class of the current method
933 * state........verifier state
935 #define TYPECHECK_LEAVE \
937 if (state->initmethod && state->m->class != class_java_lang_Object) { \
938 /* check the marker variable */ \
939 LOG("Checking <init> marker"); \
940 if (!typevectorset_checktype(state->localset,state->numlocals-1,TYPE_INT))\
941 TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'"); \
945 /* verify_invocation ***********************************************************
947 Verify an ICMD_INVOKE* instruction.
950 state............the current state of the verifier
953 true.............successful verification,
954 false............an exception has been thrown.
956 *******************************************************************************/
959 verify_invocation(verifier_state *state)
961 unresolved_method *um; /* struct describing the called method */
962 constant_FMIref *mref; /* reference to the called method */
963 methoddesc *md; /* descriptor of the called method */
964 bool specialmethod; /* true if a <...> method is called */
965 int opcode; /* invocation opcode */
966 bool callinginit; /* true if <init> is called */
968 classref_or_classinfo initclass;
970 stackelement *stack; /* temporary stack pointer */
971 stackelement *dst; /* result stack of the invocation */
973 u1 rtype; /* return type of called method */
974 static utf *name_init = NULL; /* cache for "<init>" utf string */
976 um = (unresolved_method *) state->iptr[0].target;
977 mref = um->methodref;
978 md = mref->parseddesc.md;
979 specialmethod = (mref->name->text[0] == '<');
980 opcode = state->iptr[0].opc;
981 dst = state->iptr->dst;
984 name_init = utf_new_char("<init>");
986 /* check whether we are calling <init> */
988 callinginit = (opcode == ICMD_INVOKESPECIAL && mref->name == name_init);
989 if (specialmethod && !callinginit)
990 TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
992 /* record subtype constraints for parameters */
994 if (!constrain_unresolved_method(um,state->m->class,state->m,state->iptr,state->curstack))
995 return false; /* XXX maybe wrap exception */
997 /* try to resolve the method lazily */
999 if (!resolve_method(um,resolveLazy,(methodinfo **) &(state->iptr[0].val.a)))
1003 if (opcode == ICMD_INVOKESPECIAL) {
1004 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1006 /* (If callinginit the class is checked later.) */
1009 if (!builtin_isanysubclass(myclass,mi->class))
1010 XXXTYPECHECK_VERIFYERROR_bool("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1015 /* allocate parameters if necessary */
1018 if (!descriptor_params_from_paramtypes(md,
1019 (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
1022 /* check parameter types */
1024 stack = state->curstack;
1025 i = md->paramcount; /* number of parameters including 'this'*/
1028 td = md->paramtypes + i;
1029 if (stack->type != td->type)
1030 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
1031 if (stack->type == TYPE_ADR) {
1032 LOGINFO(&(stack->typeinfo));
1033 if (i==0 && callinginit)
1035 /* first argument to <init> method */
1036 if (!TYPEINFO_IS_NEWOBJECT(stack->typeinfo))
1037 TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
1039 /* get the address of the NEW instruction */
1040 LOGINFO(&(stack->typeinfo));
1041 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo);
1043 initclass = CLASSREF_OR_CLASSINFO(ins[-1].val.a);
1045 initclass.cls = state->m->class;
1046 LOGSTR("class: "); LOGNAME(initclass); LOGNL;
1052 stack = stack->prev;
1055 LOG("checking return type");
1056 rtype = md->returntype.type;
1057 if (rtype != TYPE_VOID) {
1058 if (rtype != dst->type)
1059 TYPECHECK_VERIFYERROR_bool("Return type mismatch in method invocation");
1060 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
1065 LOG("replacing uninitialized object");
1066 /* replace uninitialized object type on stack */
1069 if (stack->type == TYPE_ADR
1070 && TYPEINFO_IS_NEWOBJECT(stack->typeinfo)
1071 && TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo) == ins)
1073 LOG("replacing uninitialized type on stack");
1075 /* If this stackslot is in the instack of
1076 * this basic block we must save the type(s)
1077 * we are going to replace.
1079 if (stack <= state->bptr->instack && !state->savedstack)
1083 LOG("saving input stack types");
1084 if (!state->savedstackbuf) {
1085 LOG("allocating savedstack buffer");
1086 state->savedstackbuf = DMNEW(stackelement, state->cd->maxstack);
1087 state->savedstackbuf->prev = NULL;
1088 for (i = 1; i < state->cd->maxstack; ++i)
1089 state->savedstackbuf[i].prev = state->savedstackbuf+(i-1);
1091 sp = state->savedstack = state->bptr->instack;
1092 copy = state->bptr->instack = state->savedstackbuf + (state->bptr->indepth-1);
1093 TYPESTACK_COPY(sp,copy);
1096 if (!typeinfo_init_class(&(stack->typeinfo),initclass))
1099 stack = stack->prev;
1101 /* replace uninitialized object type in locals */
1102 if (!typevectorset_init_object(state->localset,ins,initclass,state->numlocals))
1105 /* initializing the 'this' reference? */
1107 TYPECHECK_ASSERT(state->initmethod);
1108 /* must be <init> of current class or direct superclass */
1109 /* XXX check with classrefs */
1111 if (mi->class != m->class && mi->class != m->class->super.cls)
1112 TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
1115 /* set our marker variable to type int */
1116 LOG("setting <init> marker");
1117 typevectorset_store(state->localset,state->numlocals-1,TYPE_INT,NULL);
1120 /* initializing an instance created with NEW */
1121 /* XXX is this strictness ok? */
1122 /* XXX check with classrefs */
1124 if (mi->class != initclass.cls)
1125 TYPECHECK_VERIFYERROR_bool("Calling <init> method of the wrong class");
1132 /* verify_builtin **************************************************************
1134 Verify the call of a builtin function.
1137 state............the current state of the verifier
1140 true.............successful verification,
1141 false............an exception has been thrown.
1143 *******************************************************************************/
1146 verify_builtin(verifier_state *state)
1148 builtintable_entry *bte;
1150 stackptr dst; /* output stack of current instruction */
1152 bte = (builtintable_entry *) state->iptr[0].val.a;
1153 dst = state->iptr->dst;
1155 if (ISBUILTIN(BUILTIN_new) || ISBUILTIN(PATCHER_builtin_new)) {
1156 if (state->iptr[-1].opc != ICMD_ACONST)
1157 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without classinfo");
1158 cls = (classinfo *) state->iptr[-1].val.a;
1160 TYPECHECK_ASSERT(!cls || cls->linked);
1161 /* The following check also forbids array classes and interfaces: */
1162 if ((cls->flags & ACC_ABSTRACT) != 0)
1163 TYPECHECK_VERIFYERROR_bool("Invalid instruction: NEW creating instance of abstract class");
1165 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,state->iptr);
1167 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1168 TYPECHECK_INT(state->curstack);
1169 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1171 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1172 TYPECHECK_INT(state->curstack);
1173 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1175 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1176 TYPECHECK_INT(state->curstack);
1177 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1179 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1180 TYPECHECK_INT(state->curstack);
1181 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1183 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1184 TYPECHECK_INT(state->curstack);
1185 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1187 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1188 TYPECHECK_INT(state->curstack);
1189 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1191 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1192 TYPECHECK_INT(state->curstack);
1193 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1195 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1196 TYPECHECK_INT(state->curstack);
1197 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1199 else if (ISBUILTIN(BUILTIN_newarray))
1202 TYPECHECK_INT(state->curstack->prev);
1203 if (state->iptr[-1].opc != ICMD_ACONST)
1204 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1205 vft = (vftbl_t *)state->iptr[-1].val.a;
1207 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with unlinked class");
1208 if (!vft->arraydesc)
1209 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with non-array class");
1210 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1212 else if (ISBUILTIN(PATCHER_builtin_newarray))
1214 TYPECHECK_INT(state->curstack->prev);
1215 if (state->iptr[-1].opc != ICMD_ACONST)
1216 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1217 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[-1].val.a)))
1220 else if (ISBUILTIN(BUILTIN_newarray))
1223 TYPECHECK_INT(state->curstack->prev);
1224 if (state->iptr[-1].opc != ICMD_ACONST)
1225 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1226 vft = (vftbl_t *)state->iptr[-1].val.a;
1228 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with unlinked class");
1229 if (!vft->arraydesc)
1230 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with non-array class");
1231 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1233 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1236 TYPECHECK_ADR(state->curstack->prev);
1237 if (state->iptr[-1].opc != ICMD_ACONST)
1238 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without classinfo");
1239 vft = (vftbl_t *)state->iptr[-1].val.a;
1241 TYPECHECK_VERIFYERROR_bool("INSTANCEOF with unlinked class");
1242 if (!vft->arraydesc)
1243 TYPECHECK_VERIFYERROR_bool("internal error: builtin_arrayinstanceof with non-array class");
1245 #if !defined(__POWERPC__) && !defined(__X86_64__)
1246 else if (ISBUILTIN(BUILTIN_arraycheckcast)) {
1248 TYPECHECK_ADR(state->curstack->prev);
1249 if (state->iptr[-1].opc != ICMD_ACONST)
1250 TYPECHECK_VERIFYERROR_bool("illegal instruction: BUILTIN_arraycheckcast without classinfo");
1251 vft = (vftbl_t *)state->iptr[-1].val.a;
1253 TYPECHECK_VERIFYERROR_bool("CHECKCAST with unlinked class");
1254 if (!vft->arraydesc)
1255 TYPECHECK_VERIFYERROR_bool("internal error: builtin_arraycheckcast with non-array class");
1256 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1258 else if (ISBUILTIN(PATCHER_builtin_arraycheckcast)) {
1259 TYPECHECK_ADR(state->curstack->prev);
1260 if (state->iptr[-1].opc != ICMD_ACONST)
1261 TYPECHECK_VERIFYERROR_bool("illegal instruction: BUILTIN_arraycheckcast without classinfo");
1262 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[-1].val.a)))
1266 #if !defined(__POWERPC__) && !defined(__X86_64__)
1267 else if (ISBUILTIN(BUILTIN_aastore)) {
1268 TYPECHECK_ADR(state->curstack);
1269 TYPECHECK_INT(state->curstack->prev);
1270 TYPECHECK_ADR(state->curstack->prev->prev);
1271 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->prev->typeinfo))
1272 TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
1277 /* XXX put these checks in a function */
1278 TYPECHECK_COUNT(stat_ins_builtin_gen);
1279 builtindesc = builtin_desc;
1280 while (builtindesc->opcode && builtindesc->builtin
1281 != state->iptr->val.fp) builtindesc++;
1282 if (!builtindesc->opcode) {
1283 dolog("Builtin not in table: %s",icmd_builtin_name(state->iptr->val.fp));
1284 TYPECHECK_ASSERT(false);
1286 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1292 /* verify_basic_block **********************************************************
1294 Perform bytecode verification of a basic block.
1297 state............the current state of the verifier
1300 true.............successful verification,
1301 false............an exception has been thrown.
1303 *******************************************************************************/
1306 verify_basic_block(verifier_state *state)
1308 stackptr srcstack; /* source stack for copying and merging */
1309 int opcode; /* current opcode */
1310 int len; /* for counting instructions, etc. */
1311 bool superblockend; /* true if no fallthrough to next block */
1312 basicblock *tbptr; /* temporary for target block */
1313 stackptr dst; /* output stack of current instruction */
1314 basicblock **tptr; /* pointer into target list of switch instr. */
1315 classinfo *cls; /* temporary */
1316 bool maythrow; /* true if this instruction may throw */
1318 unresolved_field *uf; /* for field accesses */
1319 fieldinfo **fieldinfop; /* for field accesses */
1324 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->debug_nr);
1327 superblockend = false;
1328 state->bptr->flags = BBFINISHED;
1329 b_index = state->bptr - state->m->basicblocks;
1331 /* init stack at the start of this block */
1332 state->curstack = state->bptr->instack;
1334 /* determine the active exception handlers for this block */
1335 /* XXX could use a faster algorithm with sorted lists or */
1338 for (i = 0; i < state->cd->exceptiontablelength; ++i) {
1339 if ((state->cd->exceptiontable[i].start <= state->bptr) && (state->cd->exceptiontable[i].end > state->bptr)) {
1340 LOG1("active handler L%03d", state->cd->exceptiontable[i].handler->debug_nr);
1341 state->handlers[len++] = state->cd->exceptiontable + i;
1344 state->handlers[len] = NULL;
1346 /* init variable types at the start of this block */
1347 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(state->localbuf,b_index,state->numlocals),
1348 state->localset,state->numlocals);
1350 /* XXX FIXME FOR INLINING */
1352 if (state->handlers[0])
1353 for (i=0; i<state->numlocals; ++i)
1354 if (state->localset->td[i].type == TYPE_ADR
1355 && TYPEINFO_IS_NEWOBJECT(state->localset->td[i].info)) {
1356 /* XXX we do not check this for the uninitialized 'this' instance in */
1357 /* <init> methods. Otherwise there are problems with try blocks in */
1358 /* <init>. The spec seems to indicate that we should perform the test*/
1359 /* in all cases, but this fails with real code. */
1360 /* Example: org/eclipse/ui/internal/PerspectiveBarNewContributionItem*/
1361 /* of eclipse 3.0.2 */
1362 if (TYPEINFO_NEWOBJECT_INSTRUCTION(state->localset->td[i].info) != NULL) {
1363 /*show_icmd_method(state->m, state->cd, state->rd);*/
1364 printf("Uninitialized variale: %d, block: %d\n", i, state->bptr->debug_nr);
1365 TYPECHECK_VERIFYERROR_bool("Uninitialized object in local variable inside try block");
1369 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
1372 /* loop over the instructions */
1373 len = state->bptr->icount;
1374 state->iptr = state->bptr->iinstr;
1375 while (--len >= 0) {
1376 TYPECHECK_COUNT(stat_ins);
1378 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
1381 DOLOG(show_icmd(state->iptr,false)); LOGNL; LOGFLUSH;
1383 opcode = state->iptr->opc;
1384 myclass = state->iptr->method->class;
1385 dst = state->iptr->dst;
1390 /****************************************/
1391 /* STACK MANIPULATIONS */
1393 /* We just need to copy the typeinfo */
1394 /* for slots containing addresses. */
1396 /* CAUTION: We assume that the destination stack
1397 * slots were continuously allocated in
1398 * memory! (The current implementation in
1403 COPYTYPE(state->curstack,dst);
1407 COPYTYPE(state->curstack,dst);
1408 COPYTYPE(state->curstack,dst-2);
1409 COPYTYPE(state->curstack->prev,dst-1);
1413 COPYTYPE(state->curstack,dst);
1414 COPYTYPE(state->curstack,dst-3);
1415 COPYTYPE(state->curstack->prev,dst-1);
1416 COPYTYPE(state->curstack->prev->prev,dst-2);
1420 COPYTYPE(state->curstack,dst);
1421 COPYTYPE(state->curstack->prev,dst-1);
1425 COPYTYPE(state->curstack,dst);
1426 COPYTYPE(state->curstack->prev,dst-1);
1427 COPYTYPE(state->curstack,dst-3);
1428 COPYTYPE(state->curstack->prev,dst-4);
1429 COPYTYPE(state->curstack->prev->prev,dst-2);
1433 COPYTYPE(state->curstack,dst);
1434 COPYTYPE(state->curstack->prev,dst-1);
1435 COPYTYPE(state->curstack,dst-4);
1436 COPYTYPE(state->curstack->prev,dst-5);
1437 COPYTYPE(state->curstack->prev->prev,dst-2);
1438 COPYTYPE(state->curstack->prev->prev->prev,dst-3);
1442 COPYTYPE(state->curstack,dst-1);
1443 COPYTYPE(state->curstack->prev,dst);
1446 /****************************************/
1447 /* PRIMITIVE VARIABLE ACCESS */
1449 case ICMD_ILOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
1450 case ICMD_FLOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
1451 case ICMD_IINC: CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
1452 case ICMD_LLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_LONG); break;
1453 case ICMD_DLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
1455 case ICMD_FSTORE: STORE_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
1456 case ICMD_ISTORE: STORE_ONEWORD(state->iptr->op1,TYPE_INT); break;
1457 case ICMD_LSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_LONG); break;
1458 case ICMD_DSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
1460 /****************************************/
1461 /* LOADING ADDRESS FROM VARIABLE */
1464 TYPECHECK_COUNT(stat_ins_aload);
1466 /* loading a returnAddress is not allowed */
1467 if (state->jsrencountered) {
1468 if (!typevectorset_checkreference(state->localset,state->iptr->op1)) {
1469 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1471 if (typevectorset_copymergedtype(state->m,state->localset,state->iptr->op1,&(dst->typeinfo)) == -1)
1475 if (!TYPEDESC_IS_REFERENCE(state->localset->td[state->iptr->op1])) {
1476 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1478 TYPEINFO_COPY(state->localset->td[state->iptr->op1].info,dst->typeinfo);
1482 /****************************************/
1483 /* STORING ADDRESS TO VARIABLE */
1486 if (state->handlers[0] && TYPEINFO_IS_NEWOBJECT(state->curstack->typeinfo)) {
1487 TYPECHECK_VERIFYERROR_bool("Storing uninitialized object in local variable inside try block");
1490 if (TYPESTACK_IS_RETURNADDRESS(state->curstack)) {
1491 typevectorset_store_retaddr(state->localset,state->iptr->op1,&(state->curstack->typeinfo));
1494 typevectorset_store(state->localset,state->iptr->op1,TYPE_ADDRESS,
1495 &(state->curstack->typeinfo));
1499 /****************************************/
1500 /* LOADING ADDRESS FROM ARRAY */
1503 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->typeinfo))
1504 TYPECHECK_VERIFYERROR_bool("illegal instruction: AALOAD on non-reference array");
1506 if (!typeinfo_init_component(&state->curstack->prev->typeinfo,&dst->typeinfo))
1511 /****************************************/
1514 case ICMD_PUTFIELDCONST:
1515 case ICMD_PUTSTATICCONST:
1516 TYPECHECK_COUNT(stat_ins_field);
1518 uf = INSTRUCTION_PUTCONST_FIELDREF(state->iptr);
1519 fieldinfop = INSTRUCTION_PUTCONST_FIELDINFO_PTR(state->iptr);
1521 goto fieldaccess_tail;
1524 case ICMD_PUTSTATIC:
1525 TYPECHECK_COUNT(stat_ins_field);
1527 uf = (unresolved_field *) state->iptr[0].target;
1528 fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
1530 goto fieldaccess_tail;
1533 case ICMD_GETSTATIC:
1534 TYPECHECK_COUNT(stat_ins_field);
1536 uf = (unresolved_field *) state->iptr[0].target;
1537 fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
1539 /* the result is pushed on the stack */
1540 if (dst->type == TYPE_ADR) {
1541 if (!typeinfo_init_from_typedesc(uf->fieldref->parseddesc.fd,NULL,&(dst->typeinfo)))
1546 /* record the subtype constraints for this field access */
1547 if (!constrain_unresolved_field(uf,state->m->class,state->m,state->iptr,state->curstack))
1548 return false; /* XXX maybe wrap exception? */
1550 /* try to resolve the field reference */
1551 if (!resolve_field(uf,resolveLazy,fieldinfop))
1554 /* we need a patcher, so this is not a leafmethod */
1555 #if defined(__MIPS__) || defined(__POWERPC__)
1556 if (!*fieldinfop || !(*fieldinfop)->class->initialized)
1557 state->cd->method->isleafmethod = false;
1563 /****************************************/
1564 /* PRIMITIVE ARRAY ACCESS */
1566 case ICMD_ARRAYLENGTH:
1567 if (!TYPEINFO_MAYBE_ARRAY(state->curstack->typeinfo)
1568 && state->curstack->typeinfo.typeclass.cls != pseudo_class_Arraystub)
1569 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARRAYLENGTH on non-array");
1574 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1575 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1576 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1580 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1581 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1585 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1586 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1590 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1591 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1595 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_INT))
1596 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1600 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1601 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1605 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_LONG))
1606 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1611 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1612 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1613 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1617 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1618 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1622 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1623 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1627 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1628 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1632 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1633 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1637 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1638 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1642 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1643 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1647 #if defined(__POWERPC__) || defined(__X86_64__)
1649 /* we just check the basic input types and that the destination */
1650 /* is an array of references. Assignability to the actual array */
1651 /* must be checked at runtime, each time the instruction is */
1652 /* performed. (See builtin_canstore.) */
1653 TYPECHECK_ADR(state->curstack);
1654 TYPECHECK_INT(state->curstack->prev);
1655 TYPECHECK_ADR(state->curstack->prev->prev);
1656 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->prev->typeinfo))
1657 TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
1662 case ICMD_IASTORECONST:
1663 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_INT))
1664 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1668 case ICMD_LASTORECONST:
1669 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_LONG))
1670 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1674 case ICMD_BASTORECONST:
1675 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BOOLEAN)
1676 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BYTE))
1677 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1681 case ICMD_CASTORECONST:
1682 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_CHAR))
1683 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1687 case ICMD_SASTORECONST:
1688 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_SHORT))
1689 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1693 /****************************************/
1694 /* ADDRESS CONSTANTS */
1697 if (state->iptr->val.a == NULL)
1698 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1700 /* string constant (or constant for builtin function) */
1701 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1704 /****************************************/
1705 /* CHECKCAST AND INSTANCEOF */
1707 case ICMD_CHECKCAST:
1708 TYPECHECK_ADR(state->curstack);
1709 /* returnAddress is not allowed */
1710 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1711 TYPECHECK_VERIFYERROR_bool("Illegal instruction: CHECKCAST on non-reference");
1713 cls = (classinfo *) state->iptr[0].val.a;
1715 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,cls);
1717 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
1722 case ICMD_ARRAYCHECKCAST:
1723 TYPECHECK_ADR(state->curstack);
1724 /* returnAddress is not allowed */
1725 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1726 TYPECHECK_VERIFYERROR_bool("Illegal instruction: ARRAYCHECKCAST on non-reference");
1728 if (state->iptr[0].op1) {
1729 /* a resolved array class */
1730 cls = ((vftbl_t *)state->iptr[0].target)->class;
1731 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,cls);
1734 /* an unresolved array class reference */
1735 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
1741 case ICMD_INSTANCEOF:
1742 TYPECHECK_ADR(state->curstack);
1743 /* returnAddress is not allowed */
1744 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1745 TYPECHECK_VERIFYERROR_bool("Illegal instruction: INSTANCEOF on non-reference");
1748 /****************************************/
1749 /* BRANCH INSTRUCTIONS */
1752 superblockend = true;
1755 case ICMD_IFNONNULL:
1762 case ICMD_IF_ICMPEQ:
1763 case ICMD_IF_ICMPNE:
1764 case ICMD_IF_ICMPLT:
1765 case ICMD_IF_ICMPGE:
1766 case ICMD_IF_ICMPGT:
1767 case ICMD_IF_ICMPLE:
1768 case ICMD_IF_ACMPEQ:
1769 case ICMD_IF_ACMPNE:
1776 case ICMD_IF_LCMPEQ:
1777 case ICMD_IF_LCMPNE:
1778 case ICMD_IF_LCMPLT:
1779 case ICMD_IF_LCMPGE:
1780 case ICMD_IF_LCMPGT:
1781 case ICMD_IF_LCMPLE:
1782 TYPECHECK_COUNT(stat_ins_branch);
1783 tbptr = (basicblock *) state->iptr->target;
1785 /* propagate stack and variables to the target block */
1786 if (!typestate_reach(state,tbptr,dst,state->localset))
1790 /****************************************/
1793 case ICMD_TABLESWITCH:
1794 TYPECHECK_COUNT(stat_ins_switch);
1796 s4 *s4ptr = state->iptr->val.a;
1797 s4ptr++; /* skip default */
1798 i = *s4ptr++; /* low */
1799 i = *s4ptr++ - i + 2; /* +1 for default target */
1801 goto switch_instruction_tail;
1803 case ICMD_LOOKUPSWITCH:
1804 TYPECHECK_COUNT(stat_ins_switch);
1806 s4 *s4ptr = state->iptr->val.a;
1807 s4ptr++; /* skip default */
1808 i = *s4ptr++ + 1; /* count +1 for default */
1810 switch_instruction_tail:
1811 tptr = (basicblock **)state->iptr->target;
1815 LOG2("target %d is block %04d",(tptr-(basicblock **)state->iptr->target)-1,tbptr->debug_nr);
1816 if (!typestate_reach(state,tbptr,dst,state->localset))
1820 superblockend = true;
1823 /****************************************/
1824 /* ADDRESS RETURNS AND THROW */
1827 r = typeinfo_is_assignable_to_class(&state->curstack->typeinfo,
1828 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
1829 if (r == typecheck_FALSE)
1830 TYPECHECK_VERIFYERROR_bool("illegal instruction: ATHROW on non-Throwable");
1831 if (r == typecheck_FAIL)
1833 /* XXX handle typecheck_MAYBE */
1834 superblockend = true;
1839 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1840 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARETURN on non-reference");
1842 if (state->returntype.type != TYPE_ADDRESS
1843 || (r = typeinfo_is_assignable(&state->curstack->typeinfo,&(state->returntype.info)))
1845 TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1846 if (r == typecheck_FAIL)
1848 /* XXX handle typecheck_MAYBE */
1851 /****************************************/
1852 /* PRIMITIVE RETURNS */
1855 if (state->returntype.type != TYPE_INT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1859 if (state->returntype.type != TYPE_LONG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1863 if (state->returntype.type != TYPE_FLOAT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1867 if (state->returntype.type != TYPE_DOUBLE) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1871 if (state->returntype.type != TYPE_VOID) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1874 superblockend = true;
1878 /****************************************/
1879 /* SUBROUTINE INSTRUCTIONS */
1883 state->jsrencountered = true;
1885 /* This is a dirty hack. It is needed
1886 * because of the special handling of
1887 * ICMD_JSR in stack.c
1889 dst = (stackptr) state->iptr->val.a;
1891 tbptr = (basicblock *) state->iptr->target;
1892 if (state->bptr + 1 == (state->m->basicblocks + state->m->basicblockcount + 1))
1893 TYPECHECK_VERIFYERROR_bool("Illegal instruction: JSR at end of bytecode");
1894 typestack_put_retaddr(dst,state->bptr+1,state->localset);
1895 if (!typestate_reach(state,tbptr,dst,state->localset))
1898 superblockend = true;
1902 /* check returnAddress variable */
1903 if (!typevectorset_checkretaddr(state->localset,state->iptr->op1))
1904 TYPECHECK_VERIFYERROR_bool("illegal instruction: RET using non-returnAddress variable");
1906 if (!typestate_ret(state,state->iptr->op1))
1909 superblockend = true;
1912 /****************************************/
1915 case ICMD_INVOKEVIRTUAL:
1916 case ICMD_INVOKESPECIAL:
1917 case ICMD_INVOKESTATIC:
1918 case ICMD_INVOKEINTERFACE:
1919 TYPECHECK_COUNT(stat_ins_invoke);
1920 if (!verify_invocation(state))
1925 /****************************************/
1926 /* MULTIANEWARRAY */
1928 case ICMD_MULTIANEWARRAY:
1929 /* XXX make this a separate function */
1931 vftbl_t *arrayvftbl;
1932 arraydescriptor *desc;
1934 /* check the array lengths on the stack */
1935 i = state->iptr[0].op1;
1937 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
1938 srcstack = state->curstack;
1941 TYPECHECK_VERIFYERROR_bool("Unable to pop operand off an empty stack");
1942 TYPECHECK_INT(srcstack);
1943 srcstack = srcstack->prev;
1946 /* check array descriptor */
1947 if (state->iptr[0].target == NULL) {
1948 arrayvftbl = (vftbl_t*) state->iptr[0].val.a;
1950 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
1951 if ((desc = arrayvftbl->arraydesc) == NULL)
1952 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1953 if (desc->dimension < state->iptr[0].op1)
1954 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1956 /* set the array type of the result */
1957 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1960 /* XXX do checks in patcher */
1961 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].val.a)))
1968 /****************************************/
1972 TYPECHECK_COUNT(stat_ins_builtin);
1973 if (!verify_builtin(state))
1978 /****************************************/
1979 /* SIMPLE EXCEPTION THROWING TESTS */
1981 case ICMD_CHECKASIZE:
1982 /* The argument to CHECKASIZE is typechecked by
1983 * typechecking the array creation instructions. */
1986 case ICMD_CHECKNULL:
1987 /* CHECKNULL just requires that the stack top
1988 * is an address. This is checked in stack.c */
1992 /****************************************/
1993 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1994 /* REPLACED BY OTHER OPCODES */
1996 #ifdef TYPECHECK_DEBUG
1999 case ICMD_ANEWARRAY:
2000 case ICMD_MONITORENTER:
2001 case ICMD_MONITOREXIT:
2002 #if !defined(__POWERPC__) && !defined(__X86_64__)
2005 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2006 LOG("Should have been converted to builtin function call.");
2007 TYPECHECK_ASSERT(false);
2010 case ICMD_READONLY_ARG:
2011 case ICMD_CLEAR_ARGREN:
2012 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2013 LOG("Should have been replaced in stack.c.");
2014 TYPECHECK_ASSERT(false);
2018 /****************************************/
2019 /* UNCHECKED OPERATIONS */
2021 /*********************************************
2022 * Instructions below...
2023 * *) don't operate on local variables,
2024 * *) don't operate on references,
2025 * *) don't operate on returnAddresses.
2027 * (These instructions are typechecked in
2029 ********************************************/
2031 /* Instructions which may throw a runtime exception: */
2041 /* Instructions which never throw a runtime exception: */
2042 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
2052 case ICMD_IFEQ_ICONST:
2053 case ICMD_IFNE_ICONST:
2054 case ICMD_IFLT_ICONST:
2055 case ICMD_IFGE_ICONST:
2056 case ICMD_IFGT_ICONST:
2057 case ICMD_IFLE_ICONST:
2058 case ICMD_ELSE_ICONST:
2081 case ICMD_IREM0X10001:
2082 case ICMD_LREM0X10001:
2086 case ICMD_IADDCONST:
2087 case ICMD_ISUBCONST:
2088 case ICMD_IMULCONST:
2089 case ICMD_IANDCONST:
2091 case ICMD_IXORCONST:
2092 case ICMD_ISHLCONST:
2093 case ICMD_ISHRCONST:
2094 case ICMD_IUSHRCONST:
2096 case ICMD_LADDCONST:
2097 case ICMD_LSUBCONST:
2098 case ICMD_LMULCONST:
2099 case ICMD_LANDCONST:
2101 case ICMD_LXORCONST:
2102 case ICMD_LSHLCONST:
2103 case ICMD_LSHRCONST:
2104 case ICMD_LUSHRCONST:
2121 case ICMD_INT2SHORT:
2124 case ICMD_LCMPCONST:
2144 /*XXX What shall we do with the following ?*/
2145 case ICMD_CHECKEXCEPTION:
2146 case ICMD_AASTORECONST:
2147 TYPECHECK_COUNT(stat_ins_unchecked);
2150 /****************************************/
2153 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2154 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
2158 /* the output of this instruction becomes the current stack */
2159 state->curstack = dst;
2161 /* reach exception handlers for this instruction */
2163 LOG("reaching exception handlers");
2165 while (state->handlers[i]) {
2166 TYPECHECK_COUNT(stat_handlers_reached);
2167 if (state->handlers[i]->catchtype.any)
2168 state->excstack.typeinfo.typeclass = state->handlers[i]->catchtype;
2170 state->excstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
2171 if (!typestate_reach(state,
2172 state->handlers[i]->handler,
2173 &(state->excstack),state->localset))
2179 LOG("next instruction");
2181 } /* while instructions */
2183 LOG("instructions done");
2184 LOGSTR("RESULT=> ");
2185 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
2188 /* propagate stack and variables to the following block */
2189 if (!superblockend) {
2190 LOG("reaching following block");
2191 tbptr = state->bptr + 1;
2192 while (tbptr->flags == BBDELETED) {
2194 #ifdef TYPECHECK_DEBUG
2195 /* this must be checked in parse.c */
2196 if ((tbptr->debug_nr) >= state->m->basicblockcount)
2197 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
2200 if (!typestate_reach(state,tbptr,dst,state->localset))
2204 /* We may have to restore the types of the instack slots. They
2205 * have been saved if an <init> call inside the block has
2206 * modified the instack types. (see INVOKESPECIAL) */
2208 if (state->savedstack) {
2209 stackptr sp = state->bptr->instack;
2210 stackptr copy = state->savedstack;
2211 TYPECHECK_COUNT(stat_savedstack);
2212 LOG("restoring saved instack");
2213 TYPESTACK_COPY(sp,copy);
2214 state->bptr->instack = state->savedstack;
2215 state->savedstack = NULL;
2220 /* verify_init_locals **********************************************************
2222 Initialize the local variables in the verifier state.
2225 state............the current state of the verifier
2228 true.............success,
2229 false............an exception has been thrown.
2231 *******************************************************************************/
2234 verify_init_locals(verifier_state *state)
2240 /* initialize the variable types of the first block */
2241 /* to the types of the arguments */
2243 lset = MGET_TYPEVECTOR(state->localbuf,0,state->numlocals);
2247 i = state->validlocals;
2249 /* allocate parameter descriptors if necessary */
2251 if (!state->m->parseddesc->params)
2252 if (!descriptor_params_from_paramtypes(state->m->parseddesc,state->m->flags))
2255 /* if this is an instance method initialize the "this" ref type */
2257 if (!(state->m->flags & ACC_STATIC)) {
2259 TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
2260 td->type = TYPE_ADDRESS;
2261 if (state->initmethod)
2262 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
2264 TYPEINFO_INIT_CLASSINFO(td->info, state->m->class);
2269 LOG("'this' argument set.\n");
2271 /* the rest of the arguments and the return type */
2273 i = typedescriptors_init_from_methoddesc(td, state->m->parseddesc,
2275 true, /* two word types use two slots */
2276 (td - lset->td), /* skip 'this' pointer */
2277 &state->returntype);
2282 /* variables not used for arguments are initialized to TYPE_VOID */
2284 i = state->numlocals - (td - lset->td);
2286 td->type = TYPE_VOID;
2290 LOG("Arguments set.\n");
2294 /****************************************************************************/
2296 /* This is the main function of the bytecode verifier. It is called */
2297 /* directly after analyse_stack. */
2300 /* meth.............the method to verify */
2301 /* cdata............codegendata for the method */
2302 /* rdata............registerdata for the method */
2305 /* m................successful verification */
2306 /* NULL.............an exception has been thrown */
2309 /* Bytecode verification has not been tested with inlining and */
2310 /* probably does not work correctly with inlining. */
2311 /****************************************************************************/
2313 #define MAXPARAMS 255
2315 methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
2317 verifier_state state; /* current state of the verifier */
2318 int i; /* temporary counter */
2319 static utf *name_init; /* cache for utf string "<init>" */
2321 /* collect statistics */
2323 #ifdef TYPECHECK_STATISTICS
2324 int count_iterations = 0;
2325 TYPECHECK_COUNT(stat_typechecked);
2326 TYPECHECK_COUNT_FREQ(stat_locals,cdata->maxlocals,STAT_LOCALS);
2327 TYPECHECK_COUNT_FREQ(stat_blocks,meth->basicblockcount/10,STAT_BLOCKS);
2330 /* some logging on entry */
2332 LOGSTR("\n==============================================================================\n");
2333 /*DOLOG( show_icmd_method(cdata->method,cdata,rdata));*/
2334 LOGSTR("\n==============================================================================\n");
2335 LOGimpSTR("Entering typecheck: ");
2336 LOGimpSTRu(cdata->method->name);
2338 LOGimpSTRu(cdata->method->descriptor);
2339 LOGimpSTR(" (class ");
2340 LOGimpSTRu(cdata->method->class->name);
2344 /* initialize the verifier state */
2346 state.savedstackbuf = NULL;
2347 state.savedstack = NULL;
2348 state.jsrencountered = false;
2353 /* check if this method is an instance initializer method */
2356 name_init = utf_new_char("<init>");
2357 state.initmethod = (state.m->name == name_init);
2359 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
2361 i = state.m->basicblockcount;
2362 state.bptr = state.m->basicblocks;
2364 #ifdef TYPECHECK_DEBUG
2365 if (state.bptr->flags != BBFINISHED && state.bptr->flags != BBDELETED
2366 && state.bptr->flags != BBUNDEF)
2368 /*show_icmd_method(state.cd->method,state.cd,state.rd);*/
2369 LOGSTR1("block flags: %d\n",state.bptr->flags); LOGFLUSH;
2370 TYPECHECK_ASSERT(false);
2373 if (state.bptr->flags >= BBFINISHED) {
2374 state.bptr->flags = BBTYPECHECK_UNDEF;
2379 /* the first block is always reached */
2381 if (state.m->basicblockcount && state.m->basicblocks[0].flags == BBTYPECHECK_UNDEF)
2382 state.m->basicblocks[0].flags = BBTYPECHECK_REACHED;
2384 LOG("Blocks reset.\n");
2386 /* number of local variables */
2388 /* In <init> methods we use an extra local variable to indicate whether */
2389 /* the 'this' reference has been initialized. */
2390 /* TYPE_VOID...means 'this' has not been initialized, */
2391 /* TYPE_INT....means 'this' has been initialized. */
2392 state.numlocals = state.cd->maxlocals;
2393 state.validlocals = state.numlocals;
2394 if (state.initmethod) state.numlocals++;
2396 /* allocate the buffers for local variables */
2398 state.localbuf = DMNEW_TYPEVECTOR(state.m->basicblockcount+1, state.numlocals);
2399 state.localset = MGET_TYPEVECTOR(state.localbuf,state.m->basicblockcount,state.numlocals);
2401 LOG("Variable buffer allocated.\n");
2403 /* allocate the buffer of active exception handlers */
2405 state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
2407 /* initialized local variables of first block */
2409 if (!verify_init_locals(&state))
2412 /* initialize the input stack of exception handlers */
2414 state.excstack.prev = NULL;
2415 state.excstack.type = TYPE_ADR;
2416 TYPEINFO_INIT_CLASSINFO(state.excstack.typeinfo,
2417 class_java_lang_Throwable); /* changed later */
2419 LOG("Exception handler stacks set.\n");
2421 /* loop while there are still blocks to be checked */
2423 TYPECHECK_COUNT(count_iterations);
2425 state.repeat = false;
2427 i = state.m->basicblockcount;
2428 state.bptr = state.m->basicblocks;
2431 LOGSTR1("---- BLOCK %04d, ",state.bptr->debug_nr);
2432 LOGSTR1("blockflags: %d\n",state.bptr->flags);
2435 /* verify reached block */
2436 if (state.bptr->flags == BBTYPECHECK_REACHED) {
2437 if (!verify_basic_block(&state))
2441 } /* while blocks */
2443 LOGIF(state.repeat,"state.repeat == true");
2444 } while (state.repeat);
2448 #ifdef TYPECHECK_STATISTICS
2449 LOG1("Typechecker did %4d iterations",count_iterations);
2450 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2451 TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
2454 /* check for invalid flags at exit */
2455 /* XXX make this a separate function */
2457 #ifdef TYPECHECK_DEBUG
2458 for (i=0; i<state.m->basicblockcount; ++i) {
2459 if (state.m->basicblocks[i].flags != BBDELETED
2460 && state.m->basicblocks[i].flags != BBUNDEF
2461 && state.m->basicblocks[i].flags != BBFINISHED
2462 && state.m->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2463 * some exception handlers,
2466 LOG2("block L%03d has invalid flags after typecheck: %d",
2467 state.m->basicblocks[i].debug_nr,state.m->basicblocks[i].flags);
2468 TYPECHECK_ASSERT(false);
2473 /* Reset blocks we never reached */
2475 for (i=0; i<state.m->basicblockcount; ++i) {
2476 if (state.m->basicblocks[i].flags == BBTYPECHECK_UNDEF)
2477 state.m->basicblocks[i].flags = BBFINISHED;
2480 LOGimp("exiting typecheck");
2482 /* just return methodinfo* to indicate everything was ok */
2489 #endif /* CACAO_TYPECHECK */
2492 * These are local overrides for various environment variables in Emacs.
2493 * Please do not remove this and leave it at the end of the file, where
2494 * Emacs will automagically detect them.
2495 * ---------------------------------------------------------------------
2498 * indent-tabs-mode: t
2502 * vim:noexpandtab:sw=4:ts=4: