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 3333 2005-10-04 18:55:12Z twisti $
41 #include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
43 #ifdef CACAO_TYPECHECK
45 #include "mm/memory.h"
46 #include "toolbox/logging.h"
47 #include "native/native.h"
48 #include "vm/builtin.h"
49 #include "vm/jit/patcher.h"
50 #include "vm/loader.h"
51 #include "vm/options.h"
52 #include "vm/tables.h"
53 #include "vm/jit/jit.h"
54 #include "vm/jit/stack.h"
55 #include "vm/access.h"
56 #include "vm/resolve.h"
59 /****************************************************************************/
61 /****************************************************************************/
63 #ifdef TYPECHECK_DEBUG
64 #define TYPECHECK_ASSERT(cond) assert(cond)
66 #define TYPECHECK_ASSERT(cond)
69 #ifdef TYPECHECK_VERBOSE_OPT
70 bool typecheckverbose = false;
71 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
76 #ifdef TYPECHECK_VERBOSE
77 #define TYPECHECK_VERBOSE_IMPORTANT
78 #define LOG(str) DOLOG(log_text(str))
79 #define LOG1(str,a) DOLOG(dolog(str,a))
80 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
81 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
82 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
84 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
87 #define typevectorset_print(x,y,z)
89 #define LOGFLUSH DOLOG(fflush(get_logfile()))
90 #define LOGNL DOLOG(log_plain("\n"))
91 #define LOGSTR(str) DOLOG(log_plain(str))
92 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
93 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
94 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
95 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
96 #define LOGNAME(c) DOLOG(do {log_plain_utf(IS_CLASSREF(c) ? c.ref->name : c.cls->name);} while(0))
100 #define LOG2(str,a,b)
101 #define LOG3(str,a,b,c)
102 #define LOGIF(cond,str)
103 #define LOGINFO(info)
107 #define LOGSTR1(str,a)
108 #define LOGSTR2(str,a,b)
109 #define LOGSTR3(str,a,b,c)
114 #ifdef TYPECHECK_VERBOSE_IMPORTANT
115 #define LOGimp(str) DOLOG(log_text(str))
116 #define LOGimpSTR(str) DOLOG(log_plain(str))
117 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
120 #define LOGimpSTR(str)
121 #define LOGimpSTRu(utf)
124 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
130 typestack_print(FILE *file,stackptr stack)
132 #ifdef TYPEINFO_DEBUG
134 /*fprintf(file,"<%p>",stack);*/
135 typeinfo_print_stacktype(file,stack->type,&(stack->typeinfo));
137 if (stack) fprintf(file," ");
144 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
146 fprintf(file,"Stack: ");
147 typestack_print(file,instack);
148 fprintf(file," Locals:");
149 typevectorset_print(file,localset,size);
154 /****************************************************************************/
156 /****************************************************************************/
158 #ifdef TYPECHECK_DEBUG
159 /*#define TYPECHECK_STATISTICS*/
162 #ifdef TYPECHECK_STATISTICS
163 #define STAT_ITERATIONS 10
164 #define STAT_BLOCKS 10
165 #define STAT_LOCALS 16
167 static int stat_typechecked = 0;
168 static int stat_typechecked_jsr = 0;
169 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
170 static int stat_reached = 0;
171 static int stat_copied = 0;
172 static int stat_merged = 0;
173 static int stat_merging_changed = 0;
174 static int stat_backwards = 0;
175 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
176 static int stat_locals[STAT_LOCALS+1] = { 0 };
177 static int stat_ins = 0;
178 static int stat_ins_field = 0;
179 static int stat_ins_invoke = 0;
180 static int stat_ins_primload = 0;
181 static int stat_ins_aload = 0;
182 static int stat_ins_builtin = 0;
183 static int stat_ins_builtin_gen = 0;
184 static int stat_ins_branch = 0;
185 static int stat_ins_switch = 0;
186 static int stat_ins_unchecked = 0;
187 static int stat_handlers_reached = 0;
188 static int stat_savedstack = 0;
190 #define TYPECHECK_COUNT(cnt) (cnt)++
191 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
192 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
194 if ((val) < (limit)) (array)[val]++; \
195 else (array)[limit]++; \
198 static void print_freq(FILE *file,int *array,int limit)
201 for (i=0; i<limit; ++i)
202 fprintf(file," %3d: %8d\n",i,array[i]);
203 fprintf(file," >=%3d: %8d\n",limit,array[limit]);
206 void typecheck_print_statistics(FILE *file) {
207 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
208 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
209 fprintf(file,"reached blocks : %8d\n",stat_reached);
210 fprintf(file,"copied states : %8d\n",stat_copied);
211 fprintf(file,"merged states : %8d\n",stat_merged);
212 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
213 fprintf(file,"backwards branches : %8d\n",stat_backwards);
214 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
215 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
216 fprintf(file,"instructions : %8d\n",stat_ins);
217 fprintf(file," field access : %8d\n",stat_ins_field);
218 fprintf(file," invocations : %8d\n",stat_ins_invoke);
219 fprintf(file," load primitive : %8d\n",stat_ins_primload);
220 fprintf(file," load address : %8d\n",stat_ins_aload);
221 fprintf(file," builtins : %8d\n",stat_ins_builtin);
222 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
223 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
224 fprintf(file," branches : %8d\n",stat_ins_branch);
225 fprintf(file," switches : %8d\n",stat_ins_switch);
226 fprintf(file,"iterations used:\n");
227 print_freq(file,stat_iterations,STAT_ITERATIONS);
228 fprintf(file,"basic blocks per method / 10:\n");
229 print_freq(file,stat_blocks,STAT_BLOCKS);
230 fprintf(file,"locals:\n");
231 print_freq(file,stat_locals,STAT_LOCALS);
236 #define TYPECHECK_COUNT(cnt)
237 #define TYPECHECK_COUNTIF(cond,cnt)
238 #define TYPECHECK_COUNT_FREQ(array,val,limit)
242 /****************************************************************************/
243 /* MACROS FOR STACK TYPE CHECKING */
244 /****************************************************************************/
246 #define TYPECHECK_VERIFYERROR_ret(m,msg,retval) \
248 *exceptionptr = new_verifyerror((m), (msg)); \
252 #define TYPECHECK_VERIFYERROR_main(msg) TYPECHECK_VERIFYERROR_ret(state.m,(msg),NULL)
253 #define TYPECHECK_VERIFYERROR_bool(msg) TYPECHECK_VERIFYERROR_ret(state->m,(msg),false)
255 #define TYPECHECK_CHECK_TYPE(sp,tp,msg) \
257 if ((sp)->type != (tp)) { \
258 *exceptionptr = new_verifyerror(state->m, (msg)); \
263 #define TYPECHECK_INT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_INT,"Expected to find integer on stack")
264 #define TYPECHECK_LNG(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_LNG,"Expected to find long on stack")
265 #define TYPECHECK_FLT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_FLT,"Expected to find float on stack")
266 #define TYPECHECK_DBL(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_DBL,"Expected to find double on stack")
267 #define TYPECHECK_ADR(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_ADR,"Expected to find object on stack")
269 /****************************************************************************/
270 /* VERIFIER STATE STRUCT */
271 /****************************************************************************/
273 /* verifier_state - This structure keeps the current state of the */
274 /* bytecode verifier for passing it between verifier functions. */
276 typedef struct verifier_state {
277 stackptr curstack; /* input stack top for current instruction */
278 instruction *iptr; /* pointer to current instruction */
279 basicblock *bptr; /* pointer to current basic block */
281 methodinfo *m; /* the current method */
282 codegendata *cd; /* codegendata for current method */
283 registerdata *rd; /* registerdata for current method */
285 s4 numlocals; /* number of local variables */
286 s4 validlocals; /* number of Java-accessible locals */
287 void *localbuf; /* local variable types for each block start */
288 typevector *localset; /* typevector set for local variables */
289 typedescriptor returntype; /* return type of the current method */
291 stackptr savedstackbuf; /* buffer for saving the stack */
292 stackptr savedstack; /* saved instack of current block */
294 exceptiontable **handlers; /* active exception handlers */
295 stackelement excstack; /* instack for exception handlers */
297 bool repeat; /* if true, blocks are iterated over again */
298 bool initmethod; /* true if this is an "<init>" method */
299 bool jsrencountered; /* true if we there was a JSR */
302 /****************************************************************************/
303 /* TYPESTACK MACROS AND FUNCTIONS */
305 /* These macros and functions act on the 'type stack', which is a shorthand */
306 /* for the types of the stackslots of the current stack. The type of a */
307 /* stack slot is usually described by a TYPE_* constant and -- for TYPE_ADR */
308 /* -- by the typeinfo of the slot. The only thing that makes the type stack */
309 /* more complicated are returnAddresses of local subroutines, because a */
310 /* single stack slot may contain a set of more than one possible return */
311 /* address. This is handled by 'return address sets'. A return address set */
312 /* is kept as a linked list dangling off the typeinfo of the stack slot. */
313 /****************************************************************************/
315 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
316 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
318 #define TYPESTACK_IS_REFERENCE(sptr) \
319 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
321 #define TYPESTACK_RETURNADDRESSSET(sptr) \
322 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
324 #define RETURNADDRESSSET_SEEK(set,pos) \
325 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
327 #define TYPESTACK_COPY(sp,copy) \
328 do {for(; sp; sp=sp->prev, copy=copy->prev) { \
329 copy->type = sp->type; \
330 TYPEINFO_COPY(sp->typeinfo,copy->typeinfo); \
333 /* typestack_copy **************************************************************
335 Copy the types on the given stack to the destination stack.
337 This function does a straight forward copy except for returnAddress types.
338 For returnAddress slots only the return addresses corresponding to
339 typevectors in the SELECTED set are copied.
342 state............current verifier state
343 y................stack with types to copy
344 selected.........set of selected typevectors
347 *dst.............the destination stack
350 true.............success
351 false............an exception has been thrown
353 *******************************************************************************/
356 typestack_copy(verifier_state *state,stackptr dst,stackptr y,typevector *selected)
359 typeinfo_retaddr_set *sety;
360 typeinfo_retaddr_set *new;
361 typeinfo_retaddr_set **next;
364 for (;dst; dst=dst->prev, y=y->prev) {
366 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
369 if (dst->type != y->type) {
370 *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
373 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
374 if (dst->type == TYPE_ADDRESS) {
375 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
376 /* We copy the returnAddresses from the selected
379 LOG("copying returnAddress");
380 sety = TYPESTACK_RETURNADDRESSSET(y);
382 for (k=0,sel=selected; sel; sel=sel->alt) {
383 LOG1("selected k=%d",sel->k);
388 *next = DNEW(typeinfo_retaddr_set);
389 (*next)->addr = sety->addr;
390 next = &((*next)->alt);
393 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
396 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
401 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
407 /* typestack_put_retaddr *******************************************************
409 Put a returnAddress into a stack slot.
411 The stack slot receives a set of return addresses with as many members as
412 there are typevectors in the local variable set.
415 retaddr..........the returnAddress to set (a basicblock *)
416 loc..............the local variable typevector set
419 *dst.............the destination stack slot
421 *******************************************************************************/
424 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
426 TYPECHECK_ASSERT(dst->type == TYPE_ADDRESS);
428 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
429 for (;loc; loc=loc->alt) {
430 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
432 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
433 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
437 /* typestack_collapse **********************************************************
439 Collapse the given stack by shortening all return address sets to a single
443 *dst.............the destination stack to collapse
445 *******************************************************************************/
448 typestack_collapse(stackptr dst)
450 for (; dst; dst = dst->prev) {
451 if (TYPESTACK_IS_RETURNADDRESS(dst))
452 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
456 /* typestack_merge *************************************************************
458 Merge the types on one stack into the destination stack.
461 state............current state of the verifier
462 dst..............the destination stack
463 y................the second stack
466 *dst.............receives the result of the stack merge
469 typecheck_TRUE...*dst has been modified
470 typecheck_FALSE..*dst has not been modified
471 typecheck_FAIL...an exception has been thrown
473 *******************************************************************************/
475 static typecheck_result
476 typestack_merge(verifier_state *state,stackptr dst,stackptr y)
479 bool changed = false;
481 for (; dst; dst = dst->prev, y=y->prev) {
483 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
484 return typecheck_FAIL;
486 if (dst->type != y->type) {
487 *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
488 return typecheck_FAIL;
490 if (dst->type == TYPE_ADDRESS) {
491 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
492 /* dst has returnAddress type */
493 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
494 *exceptionptr = new_verifyerror(state->m,"Merging returnAddress with reference");
495 return typecheck_FAIL;
499 /* dst has reference type */
500 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
501 *exceptionptr = new_verifyerror(state->m,"Merging reference with returnAddress");
502 return typecheck_FAIL;
504 r = typeinfo_merge(state->m,&(dst->typeinfo),&(y->typeinfo));
505 if (r == typecheck_FAIL)
512 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
513 return typecheck_FAIL;
518 /* typestack_add ***************************************************************
520 Add the return addresses in the given stack at a given k-index to the
521 corresponding return address sets in the destination stack.
524 dst..............the destination stack
525 y................the second stack
526 ky...............the k-index which should be selected from the Y stack
529 *dst.............receives the result of adding the addresses
531 *******************************************************************************/
534 typestack_add(stackptr dst,stackptr y,int ky)
536 typeinfo_retaddr_set *setd;
537 typeinfo_retaddr_set *sety;
539 for (; dst; dst = dst->prev, y=y->prev) {
540 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
541 setd = TYPESTACK_RETURNADDRESSSET(dst);
542 sety = TYPESTACK_RETURNADDRESSSET(y);
543 RETURNADDRESSSET_SEEK(sety,ky);
546 setd->alt = DNEW(typeinfo_retaddr_set);
547 setd->alt->addr = sety->addr;
548 setd->alt->alt = NULL;
553 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
555 typestack_separable_with(stackptr a,stackptr b,int kb)
557 typeinfo_retaddr_set *seta;
558 typeinfo_retaddr_set *setb;
560 for (; a; a = a->prev, b = b->prev) {
562 if (TYPESTACK_IS_RETURNADDRESS(a)) {
563 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
564 seta = TYPESTACK_RETURNADDRESSSET(a);
565 setb = TYPESTACK_RETURNADDRESSSET(b);
566 RETURNADDRESSSET_SEEK(setb,kb);
568 for (;seta;seta=seta->alt)
569 if (seta->addr != setb->addr) return true;
572 TYPECHECK_ASSERT(!b);
576 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
578 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
580 typeinfo_retaddr_set *seta;
581 typeinfo_retaddr_set *setb;
583 for (; a; a = a->prev, b = b->prev) {
585 if (TYPESTACK_IS_RETURNADDRESS(a)) {
586 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
587 seta = TYPESTACK_RETURNADDRESSSET(a);
588 setb = TYPESTACK_RETURNADDRESSSET(b);
589 RETURNADDRESSSET_SEEK(seta,ka);
590 RETURNADDRESSSET_SEEK(setb,kb);
592 if (seta->addr != setb->addr) return true;
595 TYPECHECK_ASSERT(!b);
599 /****************************************************************************/
600 /* TYPESTATE FUNCTIONS */
602 /* These functions act on the 'type state', which comprises: */
603 /* - the types of the stack slots of the current stack */
604 /* - the set of type vectors describing the local variables */
605 /****************************************************************************/
607 /* typestate_merge *************************************************************
609 Merge the types of one state into the destination state.
612 state............current state of the verifier
613 deststack........the destination stack
614 destloc..........the destination set of local variable typevectors
615 ystack...........the second stack
616 yloc.............the second set of local variable typevectors
619 *deststack.......receives the result of the stack merge
620 *destloc.........receives the result of the local variable merge
623 typecheck_TRUE...destination state has been modified
624 typecheck_FALSE..destination state has not been modified
625 typecheck_FAIL...an exception has been thrown
627 *******************************************************************************/
629 static typecheck_result
630 typestate_merge(verifier_state *state,
631 stackptr deststack,typevector *destloc,
632 stackptr ystack,typevector *yloc)
634 typevector *dvec,*yvec;
636 bool changed = false;
640 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
641 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
642 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
643 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,state->numlocals)); LOGNL;
646 /* The stack is always merged. If there are returnAddresses on
647 * the stack they are ignored in this step. */
649 r = typestack_merge(state,deststack,ystack);
650 if (r == typecheck_FAIL)
654 /* If there have not been any JSRs we just have a single typevector merge */
655 if (!state->jsrencountered) {
656 r = typevector_merge(state->m,destloc,yloc,state->numlocals);
657 if (r == typecheck_FAIL)
662 for (yvec=yloc; yvec; yvec=yvec->alt) {
665 /* Check if the typestates (deststack,destloc) will be
666 * separable when (ystack,yvec) is added. */
668 if (!typestack_separable_with(deststack,ystack,ky)
669 && !typevectorset_separable_with(destloc,yvec,state->numlocals))
671 /* No, the resulting set won't be separable, thus we
672 * may merge all states in (deststack,destloc) and
675 typestack_collapse(deststack);
676 if (typevectorset_collapse(state->m,destloc,state->numlocals) == typecheck_FAIL)
677 return typecheck_FAIL;
678 if (typevector_merge(state->m,destloc,yvec,state->numlocals) == typecheck_FAIL)
679 return typecheck_FAIL;
682 /* Yes, the resulting set will be separable. Thus we check
683 * if we may merge (ystack,yvec) with a single state in
684 * (deststack,destloc). */
686 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
687 if (!typestack_separable_from(ystack,ky,deststack,kd)
688 && !typevector_separable_from(yvec,dvec,state->numlocals))
690 /* The typestate (ystack,yvec) is not separable from
691 * (deststack,dvec) by any returnAddress. Thus we may
692 * merge the states. */
694 r = typevector_merge(state->m,dvec,yvec,state->numlocals);
695 if (r == typecheck_FAIL)
703 /* The typestate (ystack,yvec) is separable from all typestates
704 * (deststack,destloc). Thus we must add this state to the
707 typestack_add(deststack,ystack,ky);
708 typevectorset_add(destloc,yvec,state->numlocals);
717 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
718 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
724 /* typestate_reach *************************************************************
726 Reach a destination block and propagate stack and local variable types
729 state............current state of the verifier
730 destblock........destination basic block
731 ystack...........stack to propagate
732 yloc.............set of local variable typevectors to propagate
735 state->repeat....set to true if the verifier must iterate again
736 over the basic blocks
739 true.............success
740 false............an exception has been thrown
742 *******************************************************************************/
745 typestate_reach(verifier_state *state,
746 basicblock *destblock,
747 stackptr ystack,typevector *yloc)
751 bool changed = false;
754 LOG1("reaching block L%03d",destblock->debug_nr);
755 TYPECHECK_COUNT(stat_reached);
757 destidx = destblock - state->cd->method->basicblocks;
758 destloc = MGET_TYPEVECTOR(state->localbuf,destidx,state->numlocals);
760 /* When branching backwards we have to check for uninitialized objects */
762 if (destblock <= state->bptr) {
766 /* XXX FIXME FOR INLINING */
769 TYPECHECK_COUNT(stat_backwards);
771 for (sp = ystack; sp; sp=sp->prev)
772 if (sp->type == TYPE_ADR &&
773 TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
774 /*printf("current: %d, dest: %d\n", state->bptr->debug_nr, destblock->debug_nr);*/
775 *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object on stack");
779 for (i=0; i<state->numlocals; ++i)
780 if (yloc->td[i].type == TYPE_ADR &&
781 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info)) {
782 *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object in local variable");
788 if (destblock->flags == BBTYPECHECK_UNDEF) {
789 /* The destblock has never been reached before */
791 TYPECHECK_COUNT(stat_copied);
792 LOG1("block (index %04d) reached first time",destidx);
794 if (!typestack_copy(state,destblock->instack,ystack,yloc))
796 COPY_TYPEVECTORSET(yloc,destloc,state->numlocals);
800 /* The destblock has already been reached before */
802 TYPECHECK_COUNT(stat_merged);
803 LOG1("block (index %04d) reached before",destidx);
805 r = typestate_merge(state,destblock->instack,destloc,ystack,yloc);
806 if (r == typecheck_FAIL)
809 TYPECHECK_COUNTIF(changed,stat_merging_changed);
814 destblock->flags = BBTYPECHECK_REACHED;
815 if (destblock <= state->bptr) {
817 state->repeat = true;
823 /* typestate_ret ***************************************************************
825 Reach the destinations of a RET instruction.
828 state............current state of the verifier
829 retindex.........index of local variable containing the returnAddress
832 state->repeat....set to true if the verifier must iterate again
833 over the basic blocks
836 true.............success
837 false............an exception has been thrown
839 *******************************************************************************/
842 typestate_ret(verifier_state *state,int retindex)
845 typevector *selected;
846 basicblock *destblock;
848 for (yvec=state->localset; yvec; ) {
849 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex])) {
850 *exceptionptr = new_verifyerror(state->m,"Illegal instruction: RET on non-returnAddress");
854 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
856 selected = typevectorset_select(&yvec,retindex,destblock);
858 if (!typestate_reach(state,destblock,state->curstack,selected))
864 /****************************************************************************/
865 /* MACROS FOR LOCAL VARIABLE CHECKING */
866 /****************************************************************************/
868 #define INDEX_ONEWORD(num) \
869 do { if((num)<0 || (num)>=state->validlocals) \
870 TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
871 #define INDEX_TWOWORD(num) \
872 do { if((num)<0 || ((num)+1)>=state->validlocals) \
873 TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
875 #define STORE_ONEWORD(num,type) \
876 do {typevectorset_store(state->localset,num,type,NULL);} while(0)
878 #define STORE_TWOWORD(num,type) \
879 do {typevectorset_store_twoword(state->localset,num,type);} while(0)
882 #ifdef TYPECHECK_VERBOSE
883 #define WORDCHECKFAULT \
885 dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n", \
886 state->iptr->op1,state->iptr->method->class->name->text, \
887 state->iptr->method->name->text,state->m->class->name->text,state->m->name->text); \
888 show_icmd(state->iptr++, false); \
889 show_icmd(state->iptr, false); \
892 #define WORDCHECKFAULT
896 #define CHECK_ONEWORD(num,tp) \
897 do {TYPECHECK_COUNT(stat_ins_primload); \
898 if (state->jsrencountered) { \
899 if (!typevectorset_checktype(state->localset,num,tp)) { \
901 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
905 if (state->localset->td[num].type != tp) { \
906 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
912 #define CHECK_TWOWORD(num,type) \
913 do {TYPECHECK_COUNT(stat_ins_primload); \
914 if (!typevectorset_checktype(state->localset,num,type)) { \
916 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
921 /****************************************************************************/
923 /****************************************************************************/
925 #define COPYTYPE(source,dest) \
926 {if ((source)->type == TYPE_ADR) \
927 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
929 #define ISBUILTIN(v) (bte->fp == (functionptr) (v))
931 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
933 * class........class of the current method
934 * state........verifier state
936 #define TYPECHECK_LEAVE \
938 if (state->initmethod && state->m->class != class_java_lang_Object) { \
939 /* check the marker variable */ \
940 LOG("Checking <init> marker"); \
941 if (!typevectorset_checktype(state->localset,state->numlocals-1,TYPE_INT))\
942 TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'"); \
946 /* verify_invocation ***********************************************************
948 Verify an ICMD_INVOKE* instruction.
951 state............the current state of the verifier
954 true.............successful verification,
955 false............an exception has been thrown.
957 *******************************************************************************/
960 verify_invocation(verifier_state *state)
962 unresolved_method *um; /* struct describing the called method */
963 constant_FMIref *mref; /* reference to the called method */
964 methoddesc *md; /* descriptor of the called method */
965 bool specialmethod; /* true if a <...> method is called */
966 int opcode; /* invocation opcode */
967 bool callinginit; /* true if <init> is called */
969 classref_or_classinfo initclass;
971 stackelement *stack; /* temporary stack pointer */
972 stackelement *dst; /* result stack of the invocation */
974 u1 rtype; /* return type of called method */
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;
983 /* prevent compiler warnings */
987 /* check whether we are calling <init> */
989 callinginit = (opcode == ICMD_INVOKESPECIAL && mref->name == utf_init);
990 if (specialmethod && !callinginit)
991 TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
993 /* record subtype constraints for parameters */
995 if (!constrain_unresolved_method(um,state->m->class,state->m,state->iptr,state->curstack))
996 return false; /* XXX maybe wrap exception */
998 /* try to resolve the method lazily */
1000 if (!resolve_method(um,resolveLazy,(methodinfo **) &(state->iptr[0].val.a)))
1004 if (opcode == ICMD_INVOKESPECIAL) {
1005 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1007 /* (If callinginit the class is checked later.) */
1010 if (!builtin_isanysubclass(myclass,mi->class))
1011 XXXTYPECHECK_VERIFYERROR_bool("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1016 /* allocate parameters if necessary */
1019 if (!descriptor_params_from_paramtypes(md,
1020 (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
1023 /* check parameter types */
1025 stack = state->curstack;
1026 i = md->paramcount; /* number of parameters including 'this'*/
1029 td = md->paramtypes + i;
1030 if (stack->type != td->type)
1031 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
1032 if (stack->type == TYPE_ADR) {
1033 LOGINFO(&(stack->typeinfo));
1034 if (i==0 && callinginit)
1036 /* first argument to <init> method */
1037 if (!TYPEINFO_IS_NEWOBJECT(stack->typeinfo))
1038 TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
1040 /* get the address of the NEW instruction */
1041 LOGINFO(&(stack->typeinfo));
1042 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo);
1044 initclass = CLASSREF_OR_CLASSINFO(ins[-1].val.a);
1046 initclass.cls = state->m->class;
1047 LOGSTR("class: "); LOGNAME(initclass); LOGNL;
1053 stack = stack->prev;
1056 LOG("checking return type");
1057 rtype = md->returntype.type;
1058 if (rtype != TYPE_VOID) {
1059 if (rtype != dst->type)
1060 TYPECHECK_VERIFYERROR_bool("Return type mismatch in method invocation");
1061 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
1066 LOG("replacing uninitialized object");
1067 /* replace uninitialized object type on stack */
1070 if (stack->type == TYPE_ADR
1071 && TYPEINFO_IS_NEWOBJECT(stack->typeinfo)
1072 && TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo) == ins)
1074 LOG("replacing uninitialized type on stack");
1076 /* If this stackslot is in the instack of
1077 * this basic block we must save the type(s)
1078 * we are going to replace.
1080 if (stack <= state->bptr->instack && !state->savedstack)
1084 LOG("saving input stack types");
1085 if (!state->savedstackbuf) {
1086 LOG("allocating savedstack buffer");
1087 state->savedstackbuf = DMNEW(stackelement, state->cd->maxstack);
1088 state->savedstackbuf->prev = NULL;
1089 for (i = 1; i < state->cd->maxstack; ++i)
1090 state->savedstackbuf[i].prev = state->savedstackbuf+(i-1);
1092 sp = state->savedstack = state->bptr->instack;
1093 copy = state->bptr->instack = state->savedstackbuf + (state->bptr->indepth-1);
1094 TYPESTACK_COPY(sp,copy);
1097 if (!typeinfo_init_class(&(stack->typeinfo),initclass))
1100 stack = stack->prev;
1102 /* replace uninitialized object type in locals */
1103 if (!typevectorset_init_object(state->localset,ins,initclass,state->numlocals))
1106 /* initializing the 'this' reference? */
1108 TYPECHECK_ASSERT(state->initmethod);
1109 /* must be <init> of current class or direct superclass */
1110 /* XXX check with classrefs */
1112 if (mi->class != m->class && mi->class != m->class->super.cls)
1113 TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
1116 /* set our marker variable to type int */
1117 LOG("setting <init> marker");
1118 typevectorset_store(state->localset,state->numlocals-1,TYPE_INT,NULL);
1121 /* initializing an instance created with NEW */
1122 /* XXX is this strictness ok? */
1123 /* XXX check with classrefs */
1125 if (mi->class != initclass.cls)
1126 TYPECHECK_VERIFYERROR_bool("Calling <init> method of the wrong class");
1133 /* verify_builtin **************************************************************
1135 Verify the call of a builtin function.
1138 state............the current state of the verifier
1141 true.............successful verification,
1142 false............an exception has been thrown.
1144 *******************************************************************************/
1147 verify_builtin(verifier_state *state)
1149 builtintable_entry *bte;
1151 stackptr dst; /* output stack of current instruction */
1153 bte = (builtintable_entry *) state->iptr[0].val.a;
1154 dst = state->iptr->dst;
1156 if (ISBUILTIN(BUILTIN_new) || ISBUILTIN(PATCHER_builtin_new)) {
1157 if (state->iptr[-1].opc != ICMD_ACONST)
1158 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without classinfo");
1159 cls = (classinfo *) state->iptr[-1].val.a;
1161 TYPECHECK_ASSERT(!cls || cls->linked);
1162 /* The following check also forbids array classes and interfaces: */
1163 if ((cls->flags & ACC_ABSTRACT) != 0)
1164 TYPECHECK_VERIFYERROR_bool("Invalid instruction: NEW creating instance of abstract class");
1166 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,state->iptr);
1168 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1169 TYPECHECK_INT(state->curstack);
1170 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1172 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1173 TYPECHECK_INT(state->curstack);
1174 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1176 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1177 TYPECHECK_INT(state->curstack);
1178 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1180 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1181 TYPECHECK_INT(state->curstack);
1182 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1184 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1185 TYPECHECK_INT(state->curstack);
1186 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1188 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1189 TYPECHECK_INT(state->curstack);
1190 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1192 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1193 TYPECHECK_INT(state->curstack);
1194 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1196 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1197 TYPECHECK_INT(state->curstack);
1198 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1200 else if (ISBUILTIN(BUILTIN_newarray))
1203 TYPECHECK_INT(state->curstack->prev);
1204 if (state->iptr[-1].opc != ICMD_ACONST)
1205 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1206 vft = (vftbl_t *)state->iptr[-1].val.a;
1208 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with unlinked class");
1209 if (!vft->arraydesc)
1210 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with non-array class");
1211 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1213 else if (ISBUILTIN(PATCHER_builtin_newarray))
1215 TYPECHECK_INT(state->curstack->prev);
1216 if (state->iptr[-1].opc != ICMD_ACONST)
1217 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1218 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[-1].val.a)))
1221 else if (ISBUILTIN(BUILTIN_newarray))
1224 TYPECHECK_INT(state->curstack->prev);
1225 if (state->iptr[-1].opc != ICMD_ACONST)
1226 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1227 vft = (vftbl_t *)state->iptr[-1].val.a;
1229 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with unlinked class");
1230 if (!vft->arraydesc)
1231 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with non-array class");
1232 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1234 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1237 TYPECHECK_ADR(state->curstack->prev);
1238 if (state->iptr[-1].opc != ICMD_ACONST)
1239 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without classinfo");
1240 vft = (vftbl_t *)state->iptr[-1].val.a;
1242 TYPECHECK_VERIFYERROR_bool("INSTANCEOF with unlinked class");
1243 if (!vft->arraydesc)
1244 TYPECHECK_VERIFYERROR_bool("internal error: builtin_arrayinstanceof with non-array class");
1248 /* XXX put these checks in a function */
1249 TYPECHECK_COUNT(stat_ins_builtin_gen);
1250 builtindesc = builtin_desc;
1251 while (builtindesc->opcode && builtindesc->builtin
1252 != state->iptr->val.fp) builtindesc++;
1253 if (!builtindesc->opcode) {
1254 dolog("Builtin not in table: %s",icmd_builtin_name(state->iptr->val.fp));
1255 TYPECHECK_ASSERT(false);
1257 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1263 /* verify_basic_block **********************************************************
1265 Perform bytecode verification of a basic block.
1268 state............the current state of the verifier
1271 true.............successful verification,
1272 false............an exception has been thrown.
1274 *******************************************************************************/
1277 verify_basic_block(verifier_state *state)
1279 stackptr srcstack; /* source stack for copying and merging */
1280 int opcode; /* current opcode */
1281 int len; /* for counting instructions, etc. */
1282 bool superblockend; /* true if no fallthrough to next block */
1283 basicblock *tbptr; /* temporary for target block */
1284 stackptr dst; /* output stack of current instruction */
1285 basicblock **tptr; /* pointer into target list of switch instr. */
1286 classinfo *cls; /* temporary */
1287 bool maythrow; /* true if this instruction may throw */
1289 unresolved_field *uf; /* for field accesses */
1290 fieldinfo **fieldinfop; /* for field accesses */
1295 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->debug_nr);
1298 superblockend = false;
1299 state->bptr->flags = BBFINISHED;
1300 b_index = state->bptr - state->m->basicblocks;
1302 /* init stack at the start of this block */
1303 state->curstack = state->bptr->instack;
1305 /* prevent compiler warnings */
1309 /* determine the active exception handlers for this block */
1310 /* XXX could use a faster algorithm with sorted lists or */
1313 for (i = 0; i < state->cd->exceptiontablelength; ++i) {
1314 if ((state->cd->exceptiontable[i].start <= state->bptr) && (state->cd->exceptiontable[i].end > state->bptr)) {
1315 LOG1("active handler L%03d", state->cd->exceptiontable[i].handler->debug_nr);
1316 state->handlers[len++] = state->cd->exceptiontable + i;
1319 state->handlers[len] = NULL;
1321 /* init variable types at the start of this block */
1322 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(state->localbuf,b_index,state->numlocals),
1323 state->localset,state->numlocals);
1325 /* XXX FIXME FOR INLINING */
1327 if (state->handlers[0])
1328 for (i=0; i<state->numlocals; ++i)
1329 if (state->localset->td[i].type == TYPE_ADR
1330 && TYPEINFO_IS_NEWOBJECT(state->localset->td[i].info)) {
1331 /* XXX we do not check this for the uninitialized 'this' instance in */
1332 /* <init> methods. Otherwise there are problems with try blocks in */
1333 /* <init>. The spec seems to indicate that we should perform the test*/
1334 /* in all cases, but this fails with real code. */
1335 /* Example: org/eclipse/ui/internal/PerspectiveBarNewContributionItem*/
1336 /* of eclipse 3.0.2 */
1337 if (TYPEINFO_NEWOBJECT_INSTRUCTION(state->localset->td[i].info) != NULL) {
1338 /*show_icmd_method(state->m, state->cd, state->rd);*/
1339 printf("Uninitialized variale: %d, block: %d\n", i, state->bptr->debug_nr);
1340 TYPECHECK_VERIFYERROR_bool("Uninitialized object in local variable inside try block");
1344 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
1347 /* loop over the instructions */
1348 len = state->bptr->icount;
1349 state->iptr = state->bptr->iinstr;
1350 while (--len >= 0) {
1351 TYPECHECK_COUNT(stat_ins);
1353 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
1356 DOLOG(show_icmd(state->iptr,false)); LOGNL; LOGFLUSH;
1358 opcode = state->iptr->opc;
1359 myclass = state->iptr->method->class;
1360 dst = state->iptr->dst;
1365 /****************************************/
1366 /* STACK MANIPULATIONS */
1368 /* We just need to copy the typeinfo */
1369 /* for slots containing addresses. */
1371 /* CAUTION: We assume that the destination stack
1372 * slots were continuously allocated in
1373 * memory! (The current implementation in
1378 COPYTYPE(state->curstack,dst);
1382 COPYTYPE(state->curstack,dst);
1383 COPYTYPE(state->curstack,dst-2);
1384 COPYTYPE(state->curstack->prev,dst-1);
1388 COPYTYPE(state->curstack,dst);
1389 COPYTYPE(state->curstack,dst-3);
1390 COPYTYPE(state->curstack->prev,dst-1);
1391 COPYTYPE(state->curstack->prev->prev,dst-2);
1395 COPYTYPE(state->curstack,dst);
1396 COPYTYPE(state->curstack->prev,dst-1);
1400 COPYTYPE(state->curstack,dst);
1401 COPYTYPE(state->curstack->prev,dst-1);
1402 COPYTYPE(state->curstack,dst-3);
1403 COPYTYPE(state->curstack->prev,dst-4);
1404 COPYTYPE(state->curstack->prev->prev,dst-2);
1408 COPYTYPE(state->curstack,dst);
1409 COPYTYPE(state->curstack->prev,dst-1);
1410 COPYTYPE(state->curstack,dst-4);
1411 COPYTYPE(state->curstack->prev,dst-5);
1412 COPYTYPE(state->curstack->prev->prev,dst-2);
1413 COPYTYPE(state->curstack->prev->prev->prev,dst-3);
1417 COPYTYPE(state->curstack,dst-1);
1418 COPYTYPE(state->curstack->prev,dst);
1421 /****************************************/
1422 /* PRIMITIVE VARIABLE ACCESS */
1424 case ICMD_ILOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
1425 case ICMD_FLOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
1426 case ICMD_IINC: CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
1427 case ICMD_LLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_LONG); break;
1428 case ICMD_DLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
1430 case ICMD_FSTORE: STORE_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
1431 case ICMD_ISTORE: STORE_ONEWORD(state->iptr->op1,TYPE_INT); break;
1432 case ICMD_LSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_LONG); break;
1433 case ICMD_DSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
1435 /****************************************/
1436 /* LOADING ADDRESS FROM VARIABLE */
1439 TYPECHECK_COUNT(stat_ins_aload);
1441 /* loading a returnAddress is not allowed */
1442 if (state->jsrencountered) {
1443 if (!typevectorset_checkreference(state->localset,state->iptr->op1)) {
1444 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1446 if (typevectorset_copymergedtype(state->m,state->localset,state->iptr->op1,&(dst->typeinfo)) == -1)
1450 if (!TYPEDESC_IS_REFERENCE(state->localset->td[state->iptr->op1])) {
1451 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1453 TYPEINFO_COPY(state->localset->td[state->iptr->op1].info,dst->typeinfo);
1457 /****************************************/
1458 /* STORING ADDRESS TO VARIABLE */
1461 if (state->handlers[0] && TYPEINFO_IS_NEWOBJECT(state->curstack->typeinfo)) {
1462 TYPECHECK_VERIFYERROR_bool("Storing uninitialized object in local variable inside try block");
1465 if (TYPESTACK_IS_RETURNADDRESS(state->curstack)) {
1466 typevectorset_store_retaddr(state->localset,state->iptr->op1,&(state->curstack->typeinfo));
1469 typevectorset_store(state->localset,state->iptr->op1,TYPE_ADDRESS,
1470 &(state->curstack->typeinfo));
1474 /****************************************/
1475 /* LOADING ADDRESS FROM ARRAY */
1478 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->typeinfo))
1479 TYPECHECK_VERIFYERROR_bool("illegal instruction: AALOAD on non-reference array");
1481 if (!typeinfo_init_component(&state->curstack->prev->typeinfo,&dst->typeinfo))
1486 /****************************************/
1489 case ICMD_PUTFIELDCONST:
1490 case ICMD_PUTSTATICCONST:
1491 TYPECHECK_COUNT(stat_ins_field);
1493 uf = INSTRUCTION_PUTCONST_FIELDREF(state->iptr);
1494 fieldinfop = INSTRUCTION_PUTCONST_FIELDINFO_PTR(state->iptr);
1496 goto fieldaccess_tail;
1499 case ICMD_PUTSTATIC:
1500 TYPECHECK_COUNT(stat_ins_field);
1502 uf = (unresolved_field *) state->iptr[0].target;
1503 fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
1505 goto fieldaccess_tail;
1508 case ICMD_GETSTATIC:
1509 TYPECHECK_COUNT(stat_ins_field);
1511 uf = (unresolved_field *) state->iptr[0].target;
1512 fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
1514 /* the result is pushed on the stack */
1515 if (dst->type == TYPE_ADR) {
1516 if (!typeinfo_init_from_typedesc(uf->fieldref->parseddesc.fd,NULL,&(dst->typeinfo)))
1521 /* record the subtype constraints for this field access */
1522 if (!constrain_unresolved_field(uf,state->m->class,state->m,state->iptr,state->curstack))
1523 return false; /* XXX maybe wrap exception? */
1525 /* try to resolve the field reference */
1526 if (!resolve_field(uf,resolveLazy,fieldinfop))
1529 /* we need a patcher, so this is not a leafmethod */
1530 #if defined(__MIPS__) || defined(__POWERPC__)
1531 if (!*fieldinfop || !(*fieldinfop)->class->initialized)
1532 state->cd->method->isleafmethod = false;
1538 /****************************************/
1539 /* PRIMITIVE ARRAY ACCESS */
1541 case ICMD_ARRAYLENGTH:
1542 if (!TYPEINFO_MAYBE_ARRAY(state->curstack->typeinfo)
1543 && state->curstack->typeinfo.typeclass.cls != pseudo_class_Arraystub)
1544 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARRAYLENGTH on non-array");
1549 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1550 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1551 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1555 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1556 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1560 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1561 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1565 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1566 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1570 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_INT))
1571 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1575 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1576 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1580 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_LONG))
1581 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1586 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1587 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1588 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1592 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1593 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1597 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1598 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1602 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1603 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1607 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1608 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1612 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1613 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1617 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1618 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1623 /* we just check the basic input types and that the */
1624 /* destination is an array of references. Assignability to */
1625 /* the actual array must be checked at runtime, each time the */
1626 /* instruction is performed. (See builtin_canstore.) */
1627 TYPECHECK_ADR(state->curstack);
1628 TYPECHECK_INT(state->curstack->prev);
1629 TYPECHECK_ADR(state->curstack->prev->prev);
1630 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->prev->typeinfo))
1631 TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
1635 case ICMD_IASTORECONST:
1636 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_INT))
1637 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1641 case ICMD_LASTORECONST:
1642 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_LONG))
1643 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1647 case ICMD_BASTORECONST:
1648 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BOOLEAN)
1649 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BYTE))
1650 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1654 case ICMD_CASTORECONST:
1655 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_CHAR))
1656 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1660 case ICMD_SASTORECONST:
1661 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_SHORT))
1662 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1666 /****************************************/
1667 /* ADDRESS CONSTANTS */
1670 if (state->iptr->val.a == NULL)
1671 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1673 /* string constant (or constant for builtin function) */
1674 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1677 /****************************************/
1678 /* CHECKCAST AND INSTANCEOF */
1680 case ICMD_CHECKCAST:
1681 TYPECHECK_ADR(state->curstack);
1682 /* returnAddress is not allowed */
1683 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1684 TYPECHECK_VERIFYERROR_bool("Illegal instruction: CHECKCAST on non-reference");
1686 cls = (classinfo *) state->iptr[0].val.a;
1688 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,cls);
1690 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
1695 case ICMD_ARRAYCHECKCAST:
1696 TYPECHECK_ADR(state->curstack);
1697 /* returnAddress is not allowed */
1698 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1699 TYPECHECK_VERIFYERROR_bool("Illegal instruction: ARRAYCHECKCAST on non-reference");
1701 if (state->iptr[0].op1) {
1702 /* a resolved array class */
1703 cls = ((vftbl_t *)state->iptr[0].target)->class;
1704 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,cls);
1707 /* an unresolved array class reference */
1708 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
1714 case ICMD_INSTANCEOF:
1715 TYPECHECK_ADR(state->curstack);
1716 /* returnAddress is not allowed */
1717 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1718 TYPECHECK_VERIFYERROR_bool("Illegal instruction: INSTANCEOF on non-reference");
1721 /****************************************/
1722 /* BRANCH INSTRUCTIONS */
1725 superblockend = true;
1728 case ICMD_IFNONNULL:
1735 case ICMD_IF_ICMPEQ:
1736 case ICMD_IF_ICMPNE:
1737 case ICMD_IF_ICMPLT:
1738 case ICMD_IF_ICMPGE:
1739 case ICMD_IF_ICMPGT:
1740 case ICMD_IF_ICMPLE:
1741 case ICMD_IF_ACMPEQ:
1742 case ICMD_IF_ACMPNE:
1749 case ICMD_IF_LCMPEQ:
1750 case ICMD_IF_LCMPNE:
1751 case ICMD_IF_LCMPLT:
1752 case ICMD_IF_LCMPGE:
1753 case ICMD_IF_LCMPGT:
1754 case ICMD_IF_LCMPLE:
1755 TYPECHECK_COUNT(stat_ins_branch);
1756 tbptr = (basicblock *) state->iptr->target;
1758 /* propagate stack and variables to the target block */
1759 if (!typestate_reach(state,tbptr,dst,state->localset))
1763 /****************************************/
1766 case ICMD_TABLESWITCH:
1767 TYPECHECK_COUNT(stat_ins_switch);
1769 s4 *s4ptr = state->iptr->val.a;
1770 s4ptr++; /* skip default */
1771 i = *s4ptr++; /* low */
1772 i = *s4ptr++ - i + 2; /* +1 for default target */
1774 goto switch_instruction_tail;
1776 case ICMD_LOOKUPSWITCH:
1777 TYPECHECK_COUNT(stat_ins_switch);
1779 s4 *s4ptr = state->iptr->val.a;
1780 s4ptr++; /* skip default */
1781 i = *s4ptr++ + 1; /* count +1 for default */
1783 switch_instruction_tail:
1784 tptr = (basicblock **)state->iptr->target;
1788 LOG2("target %d is block %04d",(tptr-(basicblock **)state->iptr->target)-1,tbptr->debug_nr);
1789 if (!typestate_reach(state,tbptr,dst,state->localset))
1793 superblockend = true;
1796 /****************************************/
1797 /* ADDRESS RETURNS AND THROW */
1800 r = typeinfo_is_assignable_to_class(&state->curstack->typeinfo,
1801 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
1802 if (r == typecheck_FALSE)
1803 TYPECHECK_VERIFYERROR_bool("illegal instruction: ATHROW on non-Throwable");
1804 if (r == typecheck_FAIL)
1806 /* XXX handle typecheck_MAYBE */
1807 superblockend = true;
1812 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1813 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARETURN on non-reference");
1815 if (state->returntype.type != TYPE_ADDRESS
1816 || (r = typeinfo_is_assignable(&state->curstack->typeinfo,&(state->returntype.info)))
1818 TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1819 if (r == typecheck_FAIL)
1821 /* XXX handle typecheck_MAYBE */
1824 /****************************************/
1825 /* PRIMITIVE RETURNS */
1828 if (state->returntype.type != TYPE_INT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1832 if (state->returntype.type != TYPE_LONG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1836 if (state->returntype.type != TYPE_FLOAT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1840 if (state->returntype.type != TYPE_DOUBLE) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1844 if (state->returntype.type != TYPE_VOID) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1847 superblockend = true;
1851 /****************************************/
1852 /* SUBROUTINE INSTRUCTIONS */
1856 state->jsrencountered = true;
1858 /* This is a dirty hack. It is needed
1859 * because of the special handling of
1860 * ICMD_JSR in stack.c
1862 dst = (stackptr) state->iptr->val.a;
1864 tbptr = (basicblock *) state->iptr->target;
1865 if (state->bptr + 1 == (state->m->basicblocks + state->m->basicblockcount + 1))
1866 TYPECHECK_VERIFYERROR_bool("Illegal instruction: JSR at end of bytecode");
1867 typestack_put_retaddr(dst,state->bptr+1,state->localset);
1868 if (!typestate_reach(state,tbptr,dst,state->localset))
1871 superblockend = true;
1875 /* check returnAddress variable */
1876 if (!typevectorset_checkretaddr(state->localset,state->iptr->op1))
1877 TYPECHECK_VERIFYERROR_bool("illegal instruction: RET using non-returnAddress variable");
1879 if (!typestate_ret(state,state->iptr->op1))
1882 superblockend = true;
1885 /****************************************/
1888 case ICMD_INVOKEVIRTUAL:
1889 case ICMD_INVOKESPECIAL:
1890 case ICMD_INVOKESTATIC:
1891 case ICMD_INVOKEINTERFACE:
1892 TYPECHECK_COUNT(stat_ins_invoke);
1893 if (!verify_invocation(state))
1898 /****************************************/
1899 /* MULTIANEWARRAY */
1901 case ICMD_MULTIANEWARRAY:
1902 /* XXX make this a separate function */
1904 vftbl_t *arrayvftbl;
1905 arraydescriptor *desc;
1907 /* check the array lengths on the stack */
1908 i = state->iptr[0].op1;
1910 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
1911 srcstack = state->curstack;
1914 TYPECHECK_VERIFYERROR_bool("Unable to pop operand off an empty stack");
1915 TYPECHECK_INT(srcstack);
1916 srcstack = srcstack->prev;
1919 /* check array descriptor */
1920 if (state->iptr[0].target == NULL) {
1921 arrayvftbl = (vftbl_t*) state->iptr[0].val.a;
1923 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
1924 if ((desc = arrayvftbl->arraydesc) == NULL)
1925 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1926 if (desc->dimension < state->iptr[0].op1)
1927 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1929 /* set the array type of the result */
1930 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1933 /* XXX do checks in patcher */
1934 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].val.a)))
1941 /****************************************/
1945 TYPECHECK_COUNT(stat_ins_builtin);
1946 if (!verify_builtin(state))
1951 /****************************************/
1952 /* SIMPLE EXCEPTION THROWING TESTS */
1954 case ICMD_CHECKNULL:
1955 /* CHECKNULL just requires that the stack top
1956 * is an address. This is checked in stack.c */
1960 /****************************************/
1961 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1962 /* REPLACED BY OTHER OPCODES */
1964 #ifdef TYPECHECK_DEBUG
1967 case ICMD_ANEWARRAY:
1968 case ICMD_MONITORENTER:
1969 case ICMD_MONITOREXIT:
1970 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
1971 LOG("Should have been converted to builtin function call.");
1972 TYPECHECK_ASSERT(false);
1975 case ICMD_READONLY_ARG:
1976 case ICMD_CLEAR_ARGREN:
1977 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
1978 LOG("Should have been replaced in stack.c.");
1979 TYPECHECK_ASSERT(false);
1983 /****************************************/
1984 /* UNCHECKED OPERATIONS */
1986 /*********************************************
1987 * Instructions below...
1988 * *) don't operate on local variables,
1989 * *) don't operate on references,
1990 * *) don't operate on returnAddresses.
1992 * (These instructions are typechecked in
1994 ********************************************/
1996 /* Instructions which may throw a runtime exception: */
2006 /* Instructions which never throw a runtime exception: */
2007 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
2017 case ICMD_IFEQ_ICONST:
2018 case ICMD_IFNE_ICONST:
2019 case ICMD_IFLT_ICONST:
2020 case ICMD_IFGE_ICONST:
2021 case ICMD_IFGT_ICONST:
2022 case ICMD_IFLE_ICONST:
2023 case ICMD_ELSE_ICONST:
2046 case ICMD_IREM0X10001:
2047 case ICMD_LREM0X10001:
2053 case ICMD_IADDCONST:
2054 case ICMD_ISUBCONST:
2055 case ICMD_IMULCONST:
2056 case ICMD_IANDCONST:
2058 case ICMD_IXORCONST:
2059 case ICMD_ISHLCONST:
2060 case ICMD_ISHRCONST:
2061 case ICMD_IUSHRCONST:
2063 case ICMD_LADDCONST:
2064 case ICMD_LSUBCONST:
2065 case ICMD_LMULCONST:
2066 case ICMD_LANDCONST:
2068 case ICMD_LXORCONST:
2069 case ICMD_LSHLCONST:
2070 case ICMD_LSHRCONST:
2071 case ICMD_LUSHRCONST:
2088 case ICMD_INT2SHORT:
2091 case ICMD_LCMPCONST:
2111 /*XXX What shall we do with the following ?*/
2112 case ICMD_AASTORECONST:
2113 TYPECHECK_COUNT(stat_ins_unchecked);
2116 /****************************************/
2119 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2120 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
2124 /* the output of this instruction becomes the current stack */
2125 state->curstack = dst;
2127 /* reach exception handlers for this instruction */
2129 LOG("reaching exception handlers");
2131 while (state->handlers[i]) {
2132 TYPECHECK_COUNT(stat_handlers_reached);
2133 if (state->handlers[i]->catchtype.any)
2134 state->excstack.typeinfo.typeclass = state->handlers[i]->catchtype;
2136 state->excstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
2137 if (!typestate_reach(state,
2138 state->handlers[i]->handler,
2139 &(state->excstack),state->localset))
2145 LOG("next instruction");
2147 } /* while instructions */
2149 LOG("instructions done");
2150 LOGSTR("RESULT=> ");
2151 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
2154 /* propagate stack and variables to the following block */
2155 if (!superblockend) {
2156 LOG("reaching following block");
2157 tbptr = state->bptr + 1;
2158 while (tbptr->flags == BBDELETED) {
2160 #ifdef TYPECHECK_DEBUG
2161 /* this must be checked in parse.c */
2162 if ((tbptr->debug_nr) >= state->m->basicblockcount)
2163 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
2166 if (!typestate_reach(state,tbptr,dst,state->localset))
2170 /* We may have to restore the types of the instack slots. They
2171 * have been saved if an <init> call inside the block has
2172 * modified the instack types. (see INVOKESPECIAL) */
2174 if (state->savedstack) {
2175 stackptr sp = state->bptr->instack;
2176 stackptr copy = state->savedstack;
2177 TYPECHECK_COUNT(stat_savedstack);
2178 LOG("restoring saved instack");
2179 TYPESTACK_COPY(sp,copy);
2180 state->bptr->instack = state->savedstack;
2181 state->savedstack = NULL;
2186 /* verify_init_locals **********************************************************
2188 Initialize the local variables in the verifier state.
2191 state............the current state of the verifier
2194 true.............success,
2195 false............an exception has been thrown.
2197 *******************************************************************************/
2200 verify_init_locals(verifier_state *state)
2206 /* initialize the variable types of the first block */
2207 /* to the types of the arguments */
2209 lset = MGET_TYPEVECTOR(state->localbuf,0,state->numlocals);
2213 i = state->validlocals;
2215 /* allocate parameter descriptors if necessary */
2217 if (!state->m->parseddesc->params)
2218 if (!descriptor_params_from_paramtypes(state->m->parseddesc,state->m->flags))
2221 /* if this is an instance method initialize the "this" ref type */
2223 if (!(state->m->flags & ACC_STATIC)) {
2225 TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
2226 td->type = TYPE_ADDRESS;
2227 if (state->initmethod)
2228 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
2230 TYPEINFO_INIT_CLASSINFO(td->info, state->m->class);
2235 LOG("'this' argument set.\n");
2237 /* the rest of the arguments and the return type */
2239 i = typedescriptors_init_from_methoddesc(td, state->m->parseddesc,
2241 true, /* two word types use two slots */
2242 (td - lset->td), /* skip 'this' pointer */
2243 &state->returntype);
2248 /* variables not used for arguments are initialized to TYPE_VOID */
2250 i = state->numlocals - (td - lset->td);
2252 td->type = TYPE_VOID;
2256 LOG("Arguments set.\n");
2260 /****************************************************************************/
2262 /* This is the main function of the bytecode verifier. It is called */
2263 /* directly after analyse_stack. */
2266 /* meth.............the method to verify */
2267 /* cdata............codegendata for the method */
2268 /* rdata............registerdata for the method */
2271 /* m................successful verification */
2272 /* NULL.............an exception has been thrown */
2275 /* Bytecode verification has not been tested with inlining and */
2276 /* probably does not work correctly with inlining. */
2277 /****************************************************************************/
2279 #define MAXPARAMS 255
2281 methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
2283 verifier_state state; /* current state of the verifier */
2284 int i; /* temporary counter */
2286 /* collect statistics */
2288 #ifdef TYPECHECK_STATISTICS
2289 int count_iterations = 0;
2290 TYPECHECK_COUNT(stat_typechecked);
2291 TYPECHECK_COUNT_FREQ(stat_locals,cdata->maxlocals,STAT_LOCALS);
2292 TYPECHECK_COUNT_FREQ(stat_blocks,meth->basicblockcount/10,STAT_BLOCKS);
2295 /* some logging on entry */
2297 LOGSTR("\n==============================================================================\n");
2298 /*DOLOG( show_icmd_method(cdata->method,cdata,rdata));*/
2299 LOGSTR("\n==============================================================================\n");
2300 LOGimpSTR("Entering typecheck: ");
2301 LOGimpSTRu(cdata->method->name);
2303 LOGimpSTRu(cdata->method->descriptor);
2304 LOGimpSTR(" (class ");
2305 LOGimpSTRu(cdata->method->class->name);
2309 /* initialize the verifier state */
2311 state.savedstackbuf = NULL;
2312 state.savedstack = NULL;
2313 state.jsrencountered = false;
2318 /* check if this method is an instance initializer method */
2320 state.initmethod = (state.m->name == utf_init);
2322 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
2324 i = state.m->basicblockcount;
2325 state.bptr = state.m->basicblocks;
2327 #ifdef TYPECHECK_DEBUG
2328 if (state.bptr->flags != BBFINISHED && state.bptr->flags != BBDELETED
2329 && state.bptr->flags != BBUNDEF)
2331 /*show_icmd_method(state.cd->method,state.cd,state.rd);*/
2332 LOGSTR1("block flags: %d\n",state.bptr->flags); LOGFLUSH;
2333 TYPECHECK_ASSERT(false);
2336 if (state.bptr->flags >= BBFINISHED) {
2337 state.bptr->flags = BBTYPECHECK_UNDEF;
2342 /* the first block is always reached */
2344 if (state.m->basicblockcount && state.m->basicblocks[0].flags == BBTYPECHECK_UNDEF)
2345 state.m->basicblocks[0].flags = BBTYPECHECK_REACHED;
2347 LOG("Blocks reset.\n");
2349 /* number of local variables */
2351 /* In <init> methods we use an extra local variable to indicate whether */
2352 /* the 'this' reference has been initialized. */
2353 /* TYPE_VOID...means 'this' has not been initialized, */
2354 /* TYPE_INT....means 'this' has been initialized. */
2355 state.numlocals = state.cd->maxlocals;
2356 state.validlocals = state.numlocals;
2357 if (state.initmethod) state.numlocals++;
2359 /* allocate the buffers for local variables */
2361 state.localbuf = DMNEW_TYPEVECTOR(state.m->basicblockcount+1, state.numlocals);
2362 state.localset = MGET_TYPEVECTOR(state.localbuf,state.m->basicblockcount,state.numlocals);
2364 LOG("Variable buffer allocated.\n");
2366 /* allocate the buffer of active exception handlers */
2368 state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
2370 /* initialized local variables of first block */
2372 if (!verify_init_locals(&state))
2375 /* initialize the input stack of exception handlers */
2377 state.excstack.prev = NULL;
2378 state.excstack.type = TYPE_ADR;
2379 TYPEINFO_INIT_CLASSINFO(state.excstack.typeinfo,
2380 class_java_lang_Throwable); /* changed later */
2382 LOG("Exception handler stacks set.\n");
2384 /* loop while there are still blocks to be checked */
2386 TYPECHECK_COUNT(count_iterations);
2388 state.repeat = false;
2390 i = state.m->basicblockcount;
2391 state.bptr = state.m->basicblocks;
2394 LOGSTR1("---- BLOCK %04d, ",state.bptr->debug_nr);
2395 LOGSTR1("blockflags: %d\n",state.bptr->flags);
2398 /* verify reached block */
2399 if (state.bptr->flags == BBTYPECHECK_REACHED) {
2400 if (!verify_basic_block(&state))
2404 } /* while blocks */
2406 LOGIF(state.repeat,"state.repeat == true");
2407 } while (state.repeat);
2411 #ifdef TYPECHECK_STATISTICS
2412 LOG1("Typechecker did %4d iterations",count_iterations);
2413 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2414 TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
2417 /* check for invalid flags at exit */
2418 /* XXX make this a separate function */
2420 #ifdef TYPECHECK_DEBUG
2421 for (i=0; i<state.m->basicblockcount; ++i) {
2422 if (state.m->basicblocks[i].flags != BBDELETED
2423 && state.m->basicblocks[i].flags != BBUNDEF
2424 && state.m->basicblocks[i].flags != BBFINISHED
2425 && state.m->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2426 * some exception handlers,
2429 LOG2("block L%03d has invalid flags after typecheck: %d",
2430 state.m->basicblocks[i].debug_nr,state.m->basicblocks[i].flags);
2431 TYPECHECK_ASSERT(false);
2436 /* Reset blocks we never reached */
2438 for (i=0; i<state.m->basicblockcount; ++i) {
2439 if (state.m->basicblocks[i].flags == BBTYPECHECK_UNDEF)
2440 state.m->basicblocks[i].flags = BBFINISHED;
2443 LOGimp("exiting typecheck");
2445 /* just return methodinfo* to indicate everything was ok */
2452 #endif /* CACAO_TYPECHECK */
2455 * These are local overrides for various environment variables in Emacs.
2456 * Please do not remove this and leave it at the end of the file, where
2457 * Emacs will automagically detect them.
2458 * ---------------------------------------------------------------------
2461 * indent-tabs-mode: t
2465 * vim:noexpandtab:sw=4:ts=4: