1 /* jit/typecheck.c - typechecking (part of bytecode verification)
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Edwin Steiner
29 $Id: typecheck.c 1415 2004-10-11 20:12:08Z jowenn $
33 #include "global.h" /* must be here because of CACAO_TYPECHECK */
35 #ifdef CACAO_TYPECHECK
45 #include "jit/stack.h"
46 #include "toolbox/logging.h"
47 #include "toolbox/memory.h"
49 /****************************************************************************/
51 /****************************************************************************/
53 #ifdef TYPECHECK_VERBOSE_OPT
54 bool typecheckverbose = false;
55 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
60 #ifdef TYPECHECK_VERBOSE
61 #define TYPECHECK_VERBOSE_IMPORTANT
62 #define LOG(str) DOLOG(log_text(str))
63 #define LOG1(str,a) DOLOG(dolog(str,a))
64 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
65 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
66 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
67 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
68 #define LOGFLUSH DOLOG(fflush(get_logfile()))
69 #define LOGNL DOLOG(log_plain("\n"))
70 #define LOGSTR(str) DOLOG(log_plain(str))
71 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
72 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
73 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
74 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
79 #define LOG3(str,a,b,c)
80 #define LOGIF(cond,str)
85 #define LOGSTR1(str,a)
86 #define LOGSTR2(str,a,b)
87 #define LOGSTR3(str,a,b,c)
91 #ifdef TYPECHECK_VERBOSE_IMPORTANT
92 #define LOGimp(str) DOLOG(log_text(str))
93 #define LOGimpSTR(str) DOLOG(log_plain(str))
94 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
97 #define LOGimpSTR(str)
98 #define LOGimpSTRu(utf)
101 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
107 typestack_print(FILE *file,stackptr stack)
110 typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
112 if (stack) fprintf(file," ");
118 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
120 fprintf(file,"Stack: ");
121 typestack_print(file,instack);
122 fprintf(file," Locals:");
123 typevectorset_print(file,localset,size);
128 /****************************************************************************/
130 /****************************************************************************/
132 #ifdef TYPECHECK_DEBUG
133 /*#define TYPECHECK_STATISTICS*/
136 #ifdef TYPECHECK_STATISTICS
137 #define STAT_ITERATIONS 10
138 #define STAT_BLOCKS 10
139 #define STAT_LOCALS 16
141 static int stat_typechecked = 0;
142 static int stat_typechecked_jsr = 0;
143 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
144 static int stat_reached = 0;
145 static int stat_copied = 0;
146 static int stat_merged = 0;
147 static int stat_merging_changed = 0;
148 static int stat_backwards = 0;
149 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
150 static int stat_locals[STAT_LOCALS+1] = { 0 };
151 static int stat_ins = 0;
152 static int stat_ins_field = 0;
153 static int stat_ins_invoke = 0;
154 static int stat_ins_primload = 0;
155 static int stat_ins_aload = 0;
156 static int stat_ins_builtin = 0;
157 static int stat_ins_builtin_gen = 0;
158 static int stat_ins_branch = 0;
159 static int stat_ins_switch = 0;
160 static int stat_ins_unchecked = 0;
161 static int stat_handlers_reached = 0;
162 static int stat_savedstack = 0;
164 #define TYPECHECK_COUNT(cnt) (cnt)++
165 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
166 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
168 if ((val) < (limit)) (array)[val]++; \
169 else (array)[limit]++; \
172 static void print_freq(FILE *file,int *array,int limit)
175 for (i=0; i<limit; ++i)
176 fprintf(file," %3d: %8d\n",i,array[i]);
177 fprintf(file," =>%3d: %8d\n",limit,array[limit]);
180 void typecheck_print_statistics(FILE *file) {
181 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
182 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
183 fprintf(file,"reached blocks : %8d\n",stat_reached);
184 fprintf(file,"copied states : %8d\n",stat_copied);
185 fprintf(file,"merged states : %8d\n",stat_merged);
186 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
187 fprintf(file,"backwards branches : %8d\n",stat_backwards);
188 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
189 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
190 fprintf(file,"instructions : %8d\n",stat_ins);
191 fprintf(file," field access : %8d\n",stat_ins_field);
192 fprintf(file," invocations : %8d\n",stat_ins_invoke);
193 fprintf(file," load primitive : %8d\n",stat_ins_primload);
194 fprintf(file," load address : %8d\n",stat_ins_aload);
195 fprintf(file," builtins : %8d\n",stat_ins_builtin);
196 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
197 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
198 fprintf(file," branches : %8d\n",stat_ins_branch);
199 fprintf(file," switches : %8d\n",stat_ins_switch);
200 fprintf(file,"iterations used:\n");
201 print_freq(file,stat_iterations,STAT_ITERATIONS);
202 fprintf(file,"basic blocks per method / 10:\n");
203 print_freq(file,stat_blocks,STAT_BLOCKS);
204 fprintf(file,"locals:\n");
205 print_freq(file,stat_locals,STAT_LOCALS);
210 #define TYPECHECK_COUNT(cnt)
211 #define TYPECHECK_COUNTIF(cond,cnt)
212 #define TYPECHECK_COUNT_FREQ(array,val,limit)
215 /****************************************************************************/
216 /* TYPESTACK FUNCTIONS */
217 /****************************************************************************/
219 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
220 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
222 #define TYPESTACK_IS_REFERENCE(sptr) \
223 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
225 #define TYPESTACK_RETURNADDRESSSET(sptr) \
226 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
228 #define RETURNADDRESSSET_SEEK(set,pos) \
229 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
231 #define TYPESTACK_COPY(sp,copy) \
232 do {for(; sp; sp=sp->prev, copy=copy->prev) { \
233 copy->type = sp->type; \
234 TYPEINFO_COPY(sp->typeinfo,copy->typeinfo); \
238 typestack_copy(stackptr dst,stackptr y,typevector *selected)
241 typeinfo_retaddr_set *sety;
242 typeinfo_retaddr_set *new;
243 typeinfo_retaddr_set **next;
246 for (;dst; dst=dst->prev, y=y->prev) {
247 if (!y) panic("Stack depth mismatch 1");
248 if (dst->type != y->type)
249 panic("Stack type mismatch 1");
250 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
251 if (dst->type == TYPE_ADDRESS) {
252 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
253 /* We copy the returnAddresses from the selected
256 LOG("copying returnAddress");
257 sety = TYPESTACK_RETURNADDRESSSET(y);
259 for (k=0,sel=selected; sel; sel=sel->alt) {
260 LOG1("selected k=%d",sel->k);
265 *next = DNEW(typeinfo_retaddr_set);
266 (*next)->addr = sety->addr;
267 next = &((*next)->alt);
270 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
273 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
277 if (y) panic("Stack depth mismatch 2");
281 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
283 #ifdef TYPECHECK_DEBUG
284 if (dst->type != TYPE_ADDRESS)
285 panic("Internal error: Storing returnAddress in non-address slot");
288 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
289 for (;loc; loc=loc->alt) {
290 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
292 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
293 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
298 typestack_collapse(stackptr dst)
300 for (; dst; dst = dst->prev) {
301 if (TYPESTACK_IS_RETURNADDRESS(dst))
302 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
307 typestack_merge(stackptr dst,stackptr y)
309 bool changed = false;
310 for (; dst; dst = dst->prev, y=y->prev) {
312 panic("Stack depth mismatch 3");
313 if (dst->type != y->type) panic("Stack type mismatch 2");
314 if (dst->type == TYPE_ADDRESS) {
315 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
316 /* dst has returnAddress type */
317 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo))
318 panic("Merging returnAddress with reference");
321 /* dst has reference type */
322 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo))
323 panic("Merging reference with returnAddress");
324 changed |= typeinfo_merge(&(dst->typeinfo),&(y->typeinfo));
328 if (y) panic("Stack depth mismatch 4");
333 typestack_add(stackptr dst,stackptr y,int ky)
335 typeinfo_retaddr_set *setd;
336 typeinfo_retaddr_set *sety;
338 for (; dst; dst = dst->prev, y=y->prev) {
339 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
340 setd = TYPESTACK_RETURNADDRESSSET(dst);
341 sety = TYPESTACK_RETURNADDRESSSET(y);
342 RETURNADDRESSSET_SEEK(sety,ky);
345 setd->alt = DNEW(typeinfo_retaddr_set);
346 setd->alt->addr = sety->addr;
347 setd->alt->alt = NULL;
352 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
354 typestack_separable_with(stackptr a,stackptr b,int kb)
356 typeinfo_retaddr_set *seta;
357 typeinfo_retaddr_set *setb;
359 for (; a; a = a->prev, b = b->prev) {
360 #ifdef TYPECHECK_DEBUG
361 if (!b) panic("Internal error: typestack_separable_from: different depth");
363 if (TYPESTACK_IS_RETURNADDRESS(a)) {
364 #ifdef TYPECHECK_DEBUG
365 if (!TYPESTACK_IS_RETURNADDRESS(b))
366 panic("Internal error: typestack_separable_from: unmergable stacks");
368 seta = TYPESTACK_RETURNADDRESSSET(a);
369 setb = TYPESTACK_RETURNADDRESSSET(b);
370 RETURNADDRESSSET_SEEK(setb,kb);
372 for (;seta;seta=seta->alt)
373 if (seta->addr != setb->addr) return true;
376 #ifdef TYPECHECK_DEBUG
377 if (b) panic("Internal error: typestack_separable_from: different depth");
382 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
384 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
386 typeinfo_retaddr_set *seta;
387 typeinfo_retaddr_set *setb;
389 for (; a; a = a->prev, b = b->prev) {
390 #ifdef TYPECHECK_DEBUG
391 if (!b) panic("Internal error: typestack_separable_from: different depth");
393 if (TYPESTACK_IS_RETURNADDRESS(a)) {
394 #ifdef TYPECHECK_DEBUG
395 if (!TYPESTACK_IS_RETURNADDRESS(b))
396 panic("Internal error: typestack_separable_from: unmergable stacks");
398 seta = TYPESTACK_RETURNADDRESSSET(a);
399 setb = TYPESTACK_RETURNADDRESSSET(b);
400 RETURNADDRESSSET_SEEK(seta,ka);
401 RETURNADDRESSSET_SEEK(setb,kb);
403 if (seta->addr != setb->addr) return true;
406 #ifdef TYPECHECK_DEBUG
407 if (b) panic("Internal error: typestack_separable_from: different depth");
412 /****************************************************************************/
413 /* TYPESTATE FUNCTIONS */
414 /****************************************************************************/
417 typestate_merge(stackptr deststack,typevector *destloc,
418 stackptr ystack,typevector *yloc,
419 int locsize,bool jsrencountered)
421 typevector *dvec,*yvec;
423 bool changed = false;
426 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
427 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
428 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
429 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
432 /* The stack is always merged. If there are returnAddresses on
433 * the stack they are ignored in this step. */
435 changed |= typestack_merge(deststack,ystack);
438 return typevector_merge(destloc,yloc,locsize);
440 for (yvec=yloc; yvec; yvec=yvec->alt) {
443 /* Check if the typestates (deststack,destloc) will be
444 * separable when (ystack,yvec) is added. */
446 if (!typestack_separable_with(deststack,ystack,ky)
447 && !typevectorset_separable_with(destloc,yvec,locsize))
449 /* No, the resulting set won't be separable, thus we
450 * may merge all states in (deststack,destloc) and
453 typestack_collapse(deststack);
454 typevectorset_collapse(destloc,locsize);
455 typevector_merge(destloc,yvec,locsize);
458 /* Yes, the resulting set will be separable. Thus we check
459 * if we may merge (ystack,yvec) with a single state in
460 * (deststack,destloc). */
462 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
463 if (!typestack_separable_from(ystack,ky,deststack,kd)
464 && !typevector_separable_from(yvec,dvec,locsize))
466 /* The typestate (ystack,yvec) is not separable from
467 * (deststack,dvec) by any returnAddress. Thus we may
468 * merge the states. */
470 changed |= typevector_merge(dvec,yvec,locsize);
476 /* The typestate (ystack,yvec) is separable from all typestates
477 * (deststack,destloc). Thus we must add this state to the
480 typestack_add(deststack,ystack,ky);
481 typevectorset_add(destloc,yvec,locsize);
490 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
491 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
499 typestate_reach(methodinfo *m, void *localbuf,
501 basicblock *destblock,
502 stackptr ystack,typevector *yloc,
503 int locsize,bool jsrencountered)
507 bool changed = false;
509 LOG1("reaching block L%03d",destblock->debug_nr);
510 TYPECHECK_COUNT(stat_reached);
512 destidx = destblock - m->basicblocks;
513 destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
515 /* When branching backwards we have to check for uninitialized objects */
517 if (destblock <= current) {
521 TYPECHECK_COUNT(stat_backwards);
523 for (sp = ystack; sp; sp=sp->prev)
524 if (sp->type == TYPE_ADR &&
525 TYPEINFO_IS_NEWOBJECT(sp->typeinfo))
526 panic("Branching backwards with uninitialized object on stack");
528 for (i=0; i<locsize; ++i)
529 if (yloc->td[i].type == TYPE_ADR &&
530 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
531 panic("Branching backwards with uninitialized object in local variable");
534 if (destblock->flags == BBTYPECHECK_UNDEF) {
535 /* The destblock has never been reached before */
537 TYPECHECK_COUNT(stat_copied);
538 LOG1("block (index %04d) reached first time",destidx);
540 typestack_copy(destblock->instack,ystack,yloc);
541 COPY_TYPEVECTORSET(yloc,destloc,locsize);
545 /* The destblock has already been reached before */
547 TYPECHECK_COUNT(stat_merged);
548 LOG1("block (index %04d) reached before",destidx);
550 changed = typestate_merge(destblock->instack,destloc,
553 TYPECHECK_COUNTIF(changed,stat_merging_changed);
558 destblock->flags = BBTYPECHECK_REACHED;
559 if (destblock <= current) {LOG("REPEAT!"); return true;}
566 typestate_ret(methodinfo *m, void *localbuf,
568 stackptr ystack,typevector *yloc,
569 int retindex,int locsize)
572 typevector *selected;
573 basicblock *destblock;
576 for (yvec=yloc; yvec; ) {
577 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
578 panic("Illegal instruction: RET on non-returnAddress");
580 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
582 selected = typevectorset_select(&yvec,retindex,destblock);
584 repeat |= typestate_reach(m, localbuf,current,destblock,
585 ystack,selected,locsize,true);
590 /****************************************************************************/
591 /* HELPER FUNCTIONS */
592 /****************************************************************************/
594 /* If a field is checked, definingclass == implementingclass */
596 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, classinfo *methodclass,
599 /* check access rights */
600 if (methodclass != definingclass) {
601 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
605 /* In the cases below, definingclass cannot be an interface */
608 if (definingclass->packagename != methodclass->packagename)
612 if (definingclass->packagename != methodclass->packagename) {
613 if (!builtin_isanysubclass(methodclass,implementingclass))
616 /* For protected access of super class members in another
617 * package the instance must be a subclass of or the same
618 * as the current class. */
619 LOG("protected access into other package");
620 implementingclass = methodclass;
624 if (definingclass != methodclass) {
625 LOG("private access");
630 panic("Invalid access flags");
635 if ((flags & ACC_STATIC) != 0) {
636 LOG("accessing STATIC member with instance");
640 if (implementingclass
641 && !TYPEINFO_IS_NULLTYPE(*instance)
642 && !TYPEINFO_IS_NEWOBJECT(*instance))
644 if (!typeinfo_is_assignable_to_classinfo(instance,
647 LOG("instance not assignable");
649 LOGSTRu(implementingclass->name); LOGNL; LOGFLUSH;
655 if ((flags & ACC_STATIC) == 0) {
656 LOG("accessing non-STATIC member without instance");
664 /****************************************************************************/
665 /* MACROS FOR LOCAL VARIABLE CHECKING */
666 /****************************************************************************/
668 #define INDEX_ONEWORD(num) \
669 do { if((num)<0 || (num)>=validlocals) \
670 panic("Invalid local variable index"); } while (0)
671 #define INDEX_TWOWORD(num) \
672 do { if((num)<0 || ((num)+1)>=validlocals) \
673 panic("Invalid local variable index"); } while (0)
675 #define STORE_ONEWORD(num,type) \
676 do {typevectorset_store(localset,num,type,NULL);} while(0)
678 #define STORE_TWOWORD(num,type) \
679 do {typevectorset_store_twoword(localset,num,type);} while(0)
681 #define CHECK_ONEWORD(num,tp) \
682 do {TYPECHECK_COUNT(stat_ins_primload); \
683 if (jsrencountered) { \
684 if (!typevectorset_checktype(localset,num,tp)) \
685 panic("Variable type mismatch"); \
688 if (localset->td[num].type != tp) \
689 panic("Variable type mismatch"); \
693 #define CHECK_TWOWORD(num,type) \
694 do {TYPECHECK_COUNT(stat_ins_primload); \
695 if (!typevectorset_checktype(localset,num,type)) \
696 panic("Variable type mismatch"); \
699 /****************************************************************************/
700 /* MACROS FOR STACK TYPE CHECKING */
701 /****************************************************************************/
703 /* These macros are for basic typechecks which were not done in stack.c */
705 #define TYPECHECK_STACK(sp,tp) \
706 do { if ((sp)->type != (tp)) \
707 panic("Wrong data type on stack"); } while(0)
709 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
710 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
711 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
712 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
713 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
715 #define TYPECHECK_ARGS1(t1) \
716 do {TYPECHECK_STACK(curstack,t1);} while (0)
717 #define TYPECHECK_ARGS2(t1,t2) \
718 do {TYPECHECK_ARGS1(t1); \
719 TYPECHECK_STACK(curstack->prev,t2);} while (0)
720 #define TYPECHECK_ARGS3(t1,t2,t3) \
721 do {TYPECHECK_ARGS2(t1,t2); \
722 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
724 /****************************************************************************/
726 /****************************************************************************/
728 #define COPYTYPE(source,dest) \
729 {if ((source)->type == TYPE_ADR) \
730 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
732 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
734 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
735 * from the current block (bptr). The types of local variables and
736 * stack slots are propagated to the target block.
738 * bptr.......current block
739 * tbptr......target block
740 * dst........current output stack pointer
741 * numlocals..number of local variables
742 * localset...current local variable vectorset
743 * localbuf...local variable vectorset buffer
744 * jsrencountered...true if a JSR has been seen
746 * repeat.....changed to true if a block before the current
749 #define TYPECHECK_REACH \
751 repeat |= typestate_reach(m, localbuf,bptr,tbptr,dst, \
752 localset,numlocals,jsrencountered); \
756 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
758 * class........class of the current method
759 * numlocals....number of local variables
760 * localset.....current local variable vectorset
761 * initmethod...true if this is an <init> method
763 #define TYPECHECK_LEAVE \
765 if (initmethod && m->class != class_java_lang_Object) { \
766 /* check the marker variable */ \
767 LOG("Checking <init> marker"); \
768 if (!typevectorset_checktype(localset,numlocals-1,TYPE_INT))\
769 panic("<init> method does not initialize 'this'"); \
773 /****************************************************************************/
775 /****************************************************************************/
777 #define MAXPARAMS 255
779 /* typecheck is called directly after analyse_stack */
781 methodinfo *typecheck(codegendata *codegendata)
783 int b_count, b_index;
784 stackptr curstack; /* input stack top for current instruction */
785 stackptr srcstack; /* source stack for copying and merging */
786 int opcode; /* current opcode */
787 int i; /* temporary counter */
788 int len; /* for counting instructions, etc. */
789 bool superblockend; /* true if no fallthrough to next block */
790 bool repeat; /* if true, blocks are iterated over again */
791 instruction *iptr; /* pointer to current instruction */
792 basicblock *bptr; /* pointer to current basic block */
793 basicblock *tbptr; /* temporary for target block */
795 int numlocals; /* number of local variables */
796 int validlocals; /* number of valid local variable indices */
797 void *localbuf; /* local variable types for each block start */
798 typevector *localset; /* typevector set for local variables */
799 typevector *lset; /* temporary pointer */
800 typedescriptor *td; /* temporary pointer */
802 stackptr savedstackbuf = NULL; /* buffer for saving the stack */
803 stackptr savedstack = NULL; /* saved instack of current block */
805 stackelement excstack; /* instack for exception handlers */
807 typedescriptor returntype; /* return type of current method */
808 u1 *ptype; /* parameter types of called method */
809 typeinfo *pinfo; /* parameter typeinfos of called method */
810 int rtype; /* return type of called method */
811 typeinfo rinfo; /* typeinfo for return type of called method */
813 stackptr dst; /* output stack of current instruction */
814 basicblock **tptr; /* pointer into target list of switch instr. */
815 exceptiontable **handlers; /* active exception handlers */
816 classinfo *cls; /* temporary */
817 bool maythrow; /* true if this instruction may throw */
818 static utf *name_init; /* "<init>" */
819 bool initmethod; /* true if this is an "<init>" method */
820 builtin_descriptor *builtindesc; /* temp. descriptor of builtin */
821 bool jsrencountered = false; /* true if we there was a JSR */
824 methodinfo *m=codegendata->method;
826 #ifdef TYPECHECK_STATISTICS
827 int count_iterations = 0;
828 TYPECHECK_COUNT(stat_typechecked);
829 TYPECHECK_COUNT_FREQ(stat_locals,m->maxlocals,STAT_LOCALS);
830 TYPECHECK_COUNT_FREQ(stat_blocks,m->basicblockcount/10,STAT_BLOCKS);
833 LOGSTR("\n==============================================================================\n");
834 DOLOG(show_icmd_method());
835 LOGSTR("\n==============================================================================\n");
836 LOGimpSTR("Entering typecheck: ");
837 LOGimpSTRu(method->name);
839 LOGimpSTRu(method->descriptor);
840 LOGimpSTR(" (class ");
841 LOGimpSTRu(method->class->name);
846 name_init = utf_new_char("<init>");
847 initmethod = (m->name == name_init);
849 /* Allocate buffer for method arguments */
851 ptype = DMNEW(u1,MAXPARAMS);
852 pinfo = DMNEW(typeinfo,MAXPARAMS);
854 LOG("Buffer allocated.\n");
856 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
857 b_count = m->basicblockcount;
858 bptr = m->basicblocks;
859 while (--b_count >= 0) {
860 #ifdef TYPECHECK_DEBUG
861 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
862 && bptr->flags != BBUNDEF)
865 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
866 panic("Internal error: Unexpected block flags in typecheck()");
869 if (bptr->flags >= BBFINISHED) {
870 bptr->flags = BBTYPECHECK_UNDEF;
875 /* The first block is always reached */
876 if (m->basicblockcount && m->basicblocks[0].flags == BBTYPECHECK_UNDEF)
877 m->basicblocks[0].flags = BBTYPECHECK_REACHED;
879 LOG("Blocks reset.\n");
881 /* number of local variables */
883 /* In <init> methods we use an extra local variable to signal if
884 * the 'this' reference has been initialized. */
885 numlocals = m->maxlocals;
886 validlocals = numlocals;
887 if (initmethod) numlocals++;
889 /* allocate the buffers for local variables */
890 localbuf = DMNEW_TYPEVECTOR(m->basicblockcount+1, numlocals);
891 localset = MGET_TYPEVECTOR(localbuf,m->basicblockcount,numlocals);
893 LOG("Variable buffer allocated.\n");
895 /* allocate the buffer of active exception handlers */
896 handlers = DMNEW(exceptiontable*, codegendata->exceptiontablelength + 1);
898 /* initialize the variable types of the first block */
899 /* to the types of the arguments */
900 lset = MGET_TYPEVECTOR(localbuf,0,numlocals);
906 /* if this is an instance method initialize the "this" ref type */
907 if (!(m->flags & ACC_STATIC)) {
909 panic("Not enough local variables for method arguments");
910 td->type = TYPE_ADDRESS;
912 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
914 TYPEINFO_INIT_CLASSINFO(td->info, m->class);
919 LOG("'this' argument set.\n");
921 /* the rest of the arguments and the return type */
922 i = typedescriptors_init_from_method_args(td, m->descriptor,
924 true, /* two word types use two slots */
927 i = numlocals - (td - lset->td);
929 td->type = TYPE_VOID;
933 LOG("Arguments set.\n");
935 /* initialize the input stack of exception handlers */
936 excstack.prev = NULL;
937 excstack.type = TYPE_ADR;
938 TYPEINFO_INIT_CLASSINFO(excstack.typeinfo,
939 class_java_lang_Throwable); /* changed later */
941 LOG("Exception handler stacks set.\n");
943 /* loop while there are still blocks to be checked */
945 TYPECHECK_COUNT(count_iterations);
949 b_count = m->basicblockcount;
950 bptr = m->basicblocks;
952 while (--b_count >= 0) {
953 LOGSTR1("---- BLOCK %04d, ",bptr-block);
954 LOGSTR1("blockflags: %d\n",bptr->flags);
957 if (bptr->flags == BBTYPECHECK_REACHED) {
958 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
961 superblockend = false;
962 bptr->flags = BBFINISHED;
963 b_index = bptr - m->basicblocks;
965 /* init stack at the start of this block */
966 curstack = bptr->instack;
968 /* determine the active exception handlers for this block */
969 /* XXX could use a faster algorithm with sorted lists or
972 for (i = 0; i < codegendata->exceptiontablelength; ++i) {
973 if ((codegendata->exceptiontable[i].start <= bptr) && (codegendata->exceptiontable[i].end > bptr)) {
974 LOG1("active handler L%03d", codegendata->exceptiontable[i].handler->debug_nr);
975 handlers[len++] = codegendata->exceptiontable + i;
978 handlers[len] = NULL;
980 /* init variable types at the start of this block */
981 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
984 for (i=0; i<numlocals; ++i)
985 if (localset->td[i].type == TYPE_ADR
986 && TYPEINFO_IS_NEWOBJECT(localset->td[i].info))
987 panic("Uninitialized object in local variable inside try block");
989 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
992 /* loop over the instructions */
996 TYPECHECK_COUNT(stat_ins);
997 DOLOG(show_icmd(iptr,false)); LOGNL; LOGFLUSH;
1000 myclass = iptr->method->class;
1006 /****************************************/
1007 /* STACK MANIPULATIONS */
1009 /* We just need to copy the typeinfo */
1010 /* for slots containing addresses. */
1012 /* XXX We assume that the destination stack
1013 * slots were continuously allocated in
1014 * memory. (The current implementation in
1019 COPYTYPE(curstack,dst);
1023 COPYTYPE(curstack,dst);
1024 COPYTYPE(curstack,dst-2);
1025 COPYTYPE(curstack->prev,dst-1);
1029 COPYTYPE(curstack,dst);
1030 COPYTYPE(curstack,dst-3);
1031 COPYTYPE(curstack->prev,dst-1);
1032 COPYTYPE(curstack->prev->prev,dst-2);
1036 COPYTYPE(curstack,dst);
1037 COPYTYPE(curstack->prev,dst-1);
1041 COPYTYPE(curstack,dst);
1042 COPYTYPE(curstack->prev,dst-1);
1043 COPYTYPE(curstack,dst-3);
1044 COPYTYPE(curstack->prev,dst-4);
1045 COPYTYPE(curstack->prev->prev,dst-2);
1049 COPYTYPE(curstack,dst);
1050 COPYTYPE(curstack->prev,dst-1);
1051 COPYTYPE(curstack,dst-4);
1052 COPYTYPE(curstack->prev,dst-5);
1053 COPYTYPE(curstack->prev->prev,dst-2);
1054 COPYTYPE(curstack->prev->prev->prev,dst-3);
1058 COPYTYPE(curstack,dst-1);
1059 COPYTYPE(curstack->prev,dst);
1062 /****************************************/
1072 /* PRIMITIVE VARIABLE ACCESS */
1074 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1075 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1076 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1077 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1078 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1080 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1081 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1082 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1083 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1085 /****************************************/
1086 /* LOADING ADDRESS FROM VARIABLE */
1089 TYPECHECK_COUNT(stat_ins_aload);
1091 /* loading a returnAddress is not allowed */
1092 if (jsrencountered) {
1093 if (!typevectorset_checkreference(localset,iptr->op1))
1094 panic("illegal instruction: ALOAD loading non-reference");
1096 typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
1099 if (!TYPEDESC_IS_REFERENCE(localset->td[iptr->op1]))
1100 panic("illegal instruction: ALOAD loading non-reference");
1101 TYPEINFO_COPY(localset->td[iptr->op1].info,dst->typeinfo);
1105 /****************************************/
1106 /* STORING ADDRESS TO VARIABLE */
1110 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1111 panic("Storing uninitialized object in local variable inside try block");
1113 if (TYPESTACK_IS_RETURNADDRESS(curstack))
1114 typevectorset_store_retaddr(localset,iptr->op1,&(curstack->typeinfo));
1116 typevectorset_store(localset,iptr->op1,TYPE_ADDRESS,
1117 &(curstack->typeinfo));
1120 /****************************************/
1121 /* LOADING ADDRESS FROM ARRAY */
1124 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1125 panic("illegal instruction: AALOAD on non-reference array");
1127 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1131 /****************************************/
1135 TYPECHECK_COUNT(stat_ins_field);
1136 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1137 panic("illegal instruction: PUTFIELD on non-reference");
1138 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo))
1139 panic("illegal instruction: PUTFIELD on array");
1141 /* check if the value is assignable to the field */
1143 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1145 if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1147 && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1149 /* uninitialized "this" instance */
1150 if (fi->class != m->class || (fi->flags & ACC_STATIC) != 0)
1151 panic("Setting unaccessible field in uninitialized object");
1154 panic("PUTFIELD on uninitialized object");
1158 if (!is_accessible(fi->flags,fi->class,fi->class, myclass,
1159 &(curstack->prev->typeinfo)))
1160 panic("PUTFIELD: field is not accessible");
1163 if (curstack->type != fi->type)
1164 panic("PUTFIELD type mismatch");
1165 if (fi->type == TYPE_ADR) {
1166 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1167 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1169 panic("PUTFIELD reference type not assignable");
1175 case ICMD_PUTSTATIC:
1176 TYPECHECK_COUNT(stat_ins_field);
1177 /* check if the value is assignable to the field */
1179 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1181 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL))
1182 panic("PUTSTATIC: field is not accessible");
1184 if (curstack->type != fi->type)
1185 panic("PUTSTATIC type mismatch");
1186 if (fi->type == TYPE_ADR) {
1187 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1188 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1190 panic("PUTSTATIC reference type not assignable");
1197 TYPECHECK_COUNT(stat_ins_field);
1198 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1199 panic("illegal instruction: GETFIELD on non-reference");
1200 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1201 panic("illegal instruction: GETFIELD on array");
1204 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1206 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,
1207 &(curstack->typeinfo)))
1208 panic("GETFIELD: field is not accessible");
1210 if (dst->type == TYPE_ADR) {
1211 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1217 case ICMD_GETSTATIC:
1218 TYPECHECK_COUNT(stat_ins_field);
1220 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1222 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL)) {
1223 printf("---------\n");
1224 utf_display(fi->class->name);
1226 utf_display(myclass->name);
1230 panic("GETSTATIC: field is not accessible");
1233 if (dst->type == TYPE_ADR) {
1234 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1240 /****************************************/
1241 /* PRIMITIVE ARRAY ACCESS */
1243 case ICMD_ARRAYLENGTH:
1244 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo)
1245 && curstack->typeinfo.typeclass != pseudo_class_Arraystub)
1246 panic("illegal instruction: ARRAYLENGTH on non-array");
1251 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1252 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1253 panic("Array type mismatch");
1257 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1258 panic("Array type mismatch");
1262 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1263 panic("Array type mismatch");
1267 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1268 panic("Array type mismatch");
1272 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1273 panic("Array type mismatch");
1277 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1278 panic("Array type mismatch");
1282 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1283 panic("Array type mismatch");
1288 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1289 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1290 panic("Array type mismatch");
1294 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1295 panic("Array type mismatch");
1299 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1300 panic("Array type mismatch");
1304 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1305 panic("Array type mismatch");
1309 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1310 panic("Array type mismatch");
1314 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1315 panic("Array type mismatch");
1319 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1320 panic("Array type mismatch");
1324 case ICMD_IASTORECONST:
1325 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_INT))
1326 panic("Array type mismatch");
1330 case ICMD_LASTORECONST:
1331 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_LONG))
1332 panic("Array type mismatch");
1336 case ICMD_BASTORECONST:
1337 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_BOOLEAN)
1338 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_BYTE))
1339 panic("Array type mismatch");
1343 case ICMD_CASTORECONST:
1344 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_CHAR))
1345 panic("Array type mismatch");
1349 case ICMD_SASTORECONST:
1350 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo, ARRAYTYPE_SHORT))
1351 panic("Array type mismatch");
1356 /****************************************/
1357 /* ADDRESS CONSTANTS */
1360 if (iptr->val.a == NULL)
1361 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1363 /* string constants (or constant for builtin function) */
1364 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1367 /****************************************/
1368 /* CHECKCAST AND INSTANCEOF */
1370 case ICMD_CHECKCAST:
1371 TYPECHECK_ADR(curstack);
1372 /* returnAddress is not allowed */
1373 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1374 panic("Illegal instruction: CHECKCAST on non-reference");
1376 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1380 case ICMD_INSTANCEOF:
1381 TYPECHECK_ADR(curstack);
1382 /* returnAddress is not allowed */
1383 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1384 panic("Illegal instruction: INSTANCEOF on non-reference");
1387 /****************************************/
1388 /* BRANCH INSTRUCTIONS */
1391 superblockend = true;
1394 case ICMD_IFNONNULL:
1401 case ICMD_IF_ICMPEQ:
1402 case ICMD_IF_ICMPNE:
1403 case ICMD_IF_ICMPLT:
1404 case ICMD_IF_ICMPGE:
1405 case ICMD_IF_ICMPGT:
1406 case ICMD_IF_ICMPLE:
1407 case ICMD_IF_ACMPEQ:
1408 case ICMD_IF_ACMPNE:
1415 case ICMD_IF_LCMPEQ:
1416 case ICMD_IF_LCMPNE:
1417 case ICMD_IF_LCMPLT:
1418 case ICMD_IF_LCMPGE:
1419 case ICMD_IF_LCMPGT:
1420 case ICMD_IF_LCMPLE:
1421 TYPECHECK_COUNT(stat_ins_branch);
1422 tbptr = (basicblock *) iptr->target;
1424 /* propagate stack and variables to the target block */
1428 /****************************************/
1431 case ICMD_TABLESWITCH:
1432 TYPECHECK_COUNT(stat_ins_switch);
1434 s4 *s4ptr = iptr->val.a;
1435 s4ptr++; /* skip default */
1436 i = *s4ptr++; /* low */
1437 i = *s4ptr++ - i + 2; /* +1 for default target */
1439 goto switch_instruction_tail;
1441 case ICMD_LOOKUPSWITCH:
1442 TYPECHECK_COUNT(stat_ins_switch);
1444 s4 *s4ptr = iptr->val.a;
1445 s4ptr++; /* skip default */
1446 i = *s4ptr++ + 1; /* count +1 for default */
1448 switch_instruction_tail:
1449 tptr = (basicblock **)iptr->target;
1453 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1457 superblockend = true;
1460 /****************************************/
1461 /* RETURNS AND THROW */
1464 if (!typeinfo_is_assignable_to_classinfo(
1465 &curstack->typeinfo,class_java_lang_Throwable))
1466 panic("illegal instruction: ATHROW on non-Throwable");
1467 superblockend = true;
1472 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1473 panic("illegal instruction: ARETURN on non-reference");
1475 if (returntype.type != TYPE_ADDRESS
1476 || !typeinfo_is_assignable(&curstack->typeinfo,&(returntype.info)))
1477 panic("Return type mismatch");
1481 if (returntype.type != TYPE_INT) panic("Return type mismatch");
1485 if (returntype.type != TYPE_LONG) panic("Return type mismatch");
1489 if (returntype.type != TYPE_FLOAT) panic("Return type mismatch");
1493 if (returntype.type != TYPE_DOUBLE) panic("Return type mismatch");
1497 if (returntype.type != TYPE_VOID) panic("Return type mismatch");
1500 superblockend = true;
1504 /****************************************/
1505 /* SUBROUTINE INSTRUCTIONS */
1509 jsrencountered = true;
1511 /* This is a dirty hack. It is needed
1512 * because of the special handling of
1513 * ICMD_JSR in stack.c
1515 dst = (stackptr) iptr->val.a;
1517 tbptr = (basicblock *) iptr->target;
1518 if (bptr + 1 == (m->basicblocks + m->basicblockcount + 1))
1519 panic("Illegal instruction: JSR at end of bytecode");
1520 typestack_put_retaddr(dst,bptr+1,localset);
1521 repeat |= typestate_reach(m, localbuf,bptr,tbptr,dst,
1522 localset,numlocals,true);
1524 superblockend = true;
1528 /* check returnAddress variable */
1529 if (!typevectorset_checkretaddr(localset,iptr->op1))
1530 panic("illegal instruction: RET using non-returnAddress variable");
1532 repeat |= typestate_ret(m, localbuf,bptr,curstack,
1533 localset,iptr->op1,numlocals);
1535 superblockend = true;
1538 /****************************************/
1541 case ICMD_INVOKEVIRTUAL:
1542 case ICMD_INVOKESPECIAL:
1543 case ICMD_INVOKESTATIC:
1544 case ICMD_INVOKEINTERFACE:
1545 TYPECHECK_COUNT(stat_ins_invoke);
1547 methodinfo *mi = (methodinfo*) iptr->val.a;
1548 bool specialmethod = (mi->name->text[0] == '<');
1549 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1551 classinfo *initclass;
1553 if (specialmethod && !callinginit)
1554 panic("Invalid invocation of special method");
1556 if (opcode == ICMD_INVOKESPECIAL) {
1557 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1559 /* (If callinginit the class is checked later.) */
1561 if (!builtin_isanysubclass(myclass,mi->class))
1562 panic("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1566 /* fetch parameter types and return type */
1568 if (opcode != ICMD_INVOKESTATIC) {
1569 ptype[0] = TYPE_ADR;
1570 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1573 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1577 /* check parameter types */
1578 srcstack = curstack;
1579 i = mi->paramcount; /* number of parameters including 'this'*/
1582 if (srcstack->type != ptype[i])
1583 panic("Parameter type mismatch in method invocation");
1584 if (srcstack->type == TYPE_ADR) {
1585 LOGINFO(&(srcstack->typeinfo));
1587 if (i==0 && callinginit)
1589 /* first argument to <init> method */
1590 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1591 panic("Calling <init> on initialized object");
1593 /* get the address of the NEW instruction */
1594 LOGINFO(&(srcstack->typeinfo));
1595 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1596 initclass = (ins) ? (classinfo*)ins[-1].val.a : m->class;
1597 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1600 /* (This is checked below.) */
1601 /* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1602 /* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1603 /* panic("Parameter reference type mismatch in <init> invocation"); */
1606 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1607 panic("Parameter reference type mismatch in method invocation");
1612 if (i) srcstack = srcstack->prev;
1615 /* XXX We should resolve the method and pass its
1616 * class as implementingclass to is_accessible. */
1617 if (!is_accessible(mi->flags,mi->class,NULL, myclass,
1618 (opcode == ICMD_INVOKESTATIC) ? NULL
1619 : &(srcstack->typeinfo)))
1620 panic("Invoking unaccessible method");
1622 LOG("checking return type");
1623 if (rtype != TYPE_VOID) {
1624 if (rtype != dst->type)
1625 panic("Return type mismatch in method invocation");
1626 TYPEINFO_COPY(rinfo,dst->typeinfo);
1630 LOG("replacing uninitialized object");
1631 /* replace uninitialized object type on stack */
1634 if (srcstack->type == TYPE_ADR
1635 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1636 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1638 LOG("replacing uninitialized type on stack");
1640 /* If this stackslot is in the instack of
1641 * this basic block we must save the type(s)
1642 * we are going to replace.
1644 if (srcstack <= bptr->instack && !savedstack)
1648 LOG("saving input stack types");
1649 if (!savedstackbuf) {
1650 LOG("allocating savedstack buffer");
1651 savedstackbuf = DMNEW(stackelement,m->maxstack);
1652 savedstackbuf->prev = NULL;
1653 for (i=1; i<m->maxstack; ++i)
1654 savedstackbuf[i].prev = savedstackbuf+(i-1);
1656 sp = savedstack = bptr->instack;
1657 copy = bptr->instack = savedstackbuf + (bptr->indepth-1);
1658 TYPESTACK_COPY(sp,copy);
1661 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1663 srcstack = srcstack->prev;
1665 /* replace uninitialized object type in locals */
1666 typevectorset_init_object(localset,ins,initclass,numlocals);
1668 /* initializing the 'this' reference? */
1670 #ifdef TYPECHECK_DEBUG
1672 panic("Internal error: calling <init> on this in non-<init> method.");
1674 /* must be <init> of current class or direct superclass */
1675 if (mi->class != m->class && mi->class != m->class->super)
1676 panic("<init> calling <init> of the wrong class");
1678 /* set our marker variable to type int */
1679 LOG("setting <init> marker");
1680 typevectorset_store(localset,numlocals-1,TYPE_INT,NULL);
1683 /* initializing an instance created with NEW */
1684 /* XXX is this strictness ok? */
1685 if (mi->class != initclass)
1686 panic("Calling <init> method of the wrong class");
1693 case ICMD_MULTIANEWARRAY:
1695 vftbl_t *arrayvftbl;
1696 arraydescriptor *desc;
1698 /* check the array lengths on the stack */
1700 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1701 srcstack = curstack;
1704 panic("MULTIANEWARRAY missing array length");
1705 if (srcstack->type != TYPE_INT)
1706 panic("MULTIANEWARRAY using non-int as array length");
1707 srcstack = srcstack->prev;
1710 /* check array descriptor */
1711 arrayvftbl = (vftbl_t*) iptr[0].val.a;
1713 panic("MULTIANEWARRAY with unlinked class");
1714 if ((desc = arrayvftbl->arraydesc) == NULL)
1715 panic("MULTIANEWARRAY with non-array class");
1716 if (desc->dimension < iptr[0].op1)
1717 panic("MULTIANEWARRAY dimension to high");
1719 /* set the array type of the result */
1720 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1726 TYPECHECK_COUNT(stat_ins_builtin);
1727 if (ISBUILTIN(BUILTIN_aastore)) {
1728 TYPECHECK_ADR(curstack);
1729 TYPECHECK_INT(curstack->prev);
1730 TYPECHECK_ADR(curstack->prev->prev);
1731 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1732 panic("illegal instruction: AASTORE to non-reference array");
1735 /* XXX put these checks in a function */
1736 TYPECHECK_COUNT(stat_ins_builtin_gen);
1737 builtindesc = builtin_desc;
1738 while (builtindesc->opcode && builtindesc->builtin
1739 != (functionptr) iptr->val.a) builtindesc++;
1740 if (!builtindesc->opcode) {
1741 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1742 panic("Internal error: builtin not found in table");
1744 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1750 TYPECHECK_COUNT(stat_ins_builtin);
1751 if (ISBUILTIN(BUILTIN_newarray))
1754 TYPECHECK_INT(curstack->prev);
1755 if (iptr[-1].opc != ICMD_ACONST)
1756 panic("illegal instruction: builtin_newarray without classinfo");
1757 vft = (vftbl_t *)iptr[-1].val.a;
1759 panic("ANEWARRAY with unlinked class");
1760 if (!vft->arraydesc)
1761 panic("ANEWARRAY with non-array class");
1762 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1764 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1767 TYPECHECK_ADR(curstack->prev);
1768 if (iptr[-1].opc != ICMD_ACONST)
1769 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1770 vft = (vftbl_t *)iptr[-1].val.a;
1772 panic("INSTANCEOF with unlinked class");
1773 if (!vft->arraydesc)
1774 panic("internal error: builtin_arrayinstanceof with non-array class");
1776 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1778 TYPECHECK_ADR(curstack->prev);
1779 if (iptr[-1].opc != ICMD_ACONST)
1780 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1781 vft = (vftbl_t *)iptr[-1].val.a;
1783 panic("CHECKCAST with unlinked class");
1784 if (!vft->arraydesc)
1785 panic("internal error: builtin_checkarraycast with non-array class");
1786 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1789 TYPECHECK_COUNT(stat_ins_builtin_gen);
1790 builtindesc = builtin_desc;
1791 while (builtindesc->opcode && builtindesc->builtin
1792 != (functionptr) iptr->val.a) builtindesc++;
1793 if (!builtindesc->opcode) {
1794 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1795 panic("Internal error: builtin not found in table");
1797 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1803 TYPECHECK_COUNT(stat_ins_builtin);
1804 if (ISBUILTIN(BUILTIN_new)) {
1806 if (iptr[-1].opc != ICMD_ACONST)
1807 panic("illegal instruction: builtin_new without classinfo");
1808 cls = (classinfo *) iptr[-1].val.a;
1810 panic("Internal error: NEW with unlinked class");
1811 /* The following check also forbids array classes and interfaces: */
1812 if ((cls->flags & ACC_ABSTRACT) != 0)
1813 panic("Invalid instruction: NEW creating instance of abstract class");
1814 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1816 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1817 TYPECHECK_INT(curstack);
1818 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1820 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1821 TYPECHECK_INT(curstack);
1822 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1824 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1825 TYPECHECK_INT(curstack);
1826 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1828 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1829 TYPECHECK_INT(curstack);
1830 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1832 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1833 TYPECHECK_INT(curstack);
1834 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1836 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1837 TYPECHECK_INT(curstack);
1838 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1840 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1841 TYPECHECK_INT(curstack);
1842 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1844 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1845 TYPECHECK_INT(curstack);
1846 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1849 TYPECHECK_COUNT(stat_ins_builtin_gen);
1850 builtindesc = builtin_desc;
1851 while (builtindesc->opcode && builtindesc->builtin
1852 != (functionptr) iptr->val.a) builtindesc++;
1853 if (!builtindesc->opcode) {
1854 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1855 panic("Internal error: builtin not found in table");
1857 TYPECHECK_ARGS1(builtindesc->type_s1);
1862 /****************************************/
1863 /* SIMPLE EXCEPTION THROWING TESTS */
1865 case ICMD_CHECKASIZE:
1866 /* The argument to CHECKASIZE is typechecked by
1867 * typechecking the array creation instructions. */
1870 case ICMD_NULLCHECKPOP:
1871 /* NULLCHECKPOP just requires that the stack top
1872 * is an address. This is checked in stack.c */
1877 /****************************************/
1878 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1879 /* REPLACED BY OTHER OPCODES */
1881 #ifdef TYPECHECK_DEBUG
1884 case ICMD_ANEWARRAY:
1885 case ICMD_MONITORENTER:
1886 case ICMD_MONITOREXIT:
1888 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1889 LOG("Should have been converted to builtin function call.");
1890 panic("Internal error: unexpected instruction encountered");
1893 case ICMD_READONLY_ARG:
1894 case ICMD_CLEAR_ARGREN:
1895 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1896 LOG("Should have been replaced in stack.c.");
1897 panic("Internal error: unexpected pseudo instruction encountered");
1901 /****************************************/
1902 /* UNCHECKED OPERATIONS */
1904 /*********************************************
1905 * Instructions below...
1906 * *) don't operate on local variables,
1907 * *) don't operate on references,
1908 * *) don't operate on returnAddresses.
1910 * (These instructions are typechecked in
1912 ********************************************/
1914 /* Instructions which may throw a runtime exception: */
1924 /* Instructions which never throw a runtime exception: */
1925 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
1935 case ICMD_IFEQ_ICONST:
1936 case ICMD_IFNE_ICONST:
1937 case ICMD_IFLT_ICONST:
1938 case ICMD_IFGE_ICONST:
1939 case ICMD_IFGT_ICONST:
1940 case ICMD_IFLE_ICONST:
1941 case ICMD_ELSE_ICONST:
1963 case ICMD_IREM0X10001:
1964 case ICMD_LREM0X10001:
1967 case ICMD_IADDCONST:
1968 case ICMD_ISUBCONST:
1969 case ICMD_IMULCONST:
1970 case ICMD_IANDCONST:
1972 case ICMD_IXORCONST:
1973 case ICMD_ISHLCONST:
1974 case ICMD_ISHRCONST:
1975 case ICMD_IUSHRCONST:
1977 case ICMD_LADDCONST:
1978 case ICMD_LSUBCONST:
1979 case ICMD_LMULCONST:
1980 case ICMD_LANDCONST:
1982 case ICMD_LXORCONST:
1983 case ICMD_LSHLCONST:
1984 case ICMD_LSHRCONST:
1985 case ICMD_LUSHRCONST:
2002 case ICMD_INT2SHORT:
2005 case ICMD_LCMPCONST:
2024 TYPECHECK_COUNT(stat_ins_unchecked);
2027 /****************************************/
2030 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2031 panic("Missing ICMD code during typecheck");
2035 /* the output of this instruction becomes the current stack */
2038 /* reach exception handlers for this instruction */
2040 LOG("reaching exception handlers");
2042 while (handlers[i]) {
2043 TYPECHECK_COUNT(stat_handlers_reached);
2044 cls = handlers[i]->catchtype;
2045 excstack.typeinfo.typeclass = (cls) ? cls
2046 : class_java_lang_Throwable;
2047 repeat |= typestate_reach(m, localbuf,bptr,
2048 handlers[i]->handler,
2057 } /* while instructions */
2059 LOG("instructions done");
2060 LOGSTR("RESULT=> ");
2061 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
2064 /* propagate stack and variables to the following block */
2065 if (!superblockend) {
2066 LOG("reaching following block");
2068 while (tbptr->flags == BBDELETED) {
2070 #ifdef TYPECHECK_DEBUG
2071 if ((tbptr-block) >= m->basicblockcount)
2072 panic("Control flow falls off the last block");
2078 /* We may have to restore the types of the instack slots. They
2079 * have been saved if an <init> call inside the block has
2080 * modified the instack types. (see INVOKESPECIAL) */
2083 stackptr sp = bptr->instack;
2084 stackptr copy = savedstack;
2085 TYPECHECK_COUNT(stat_savedstack);
2086 LOG("restoring saved instack");
2087 TYPESTACK_COPY(sp,copy);
2088 bptr->instack = savedstack;
2092 } /* if block has to be checked */
2094 } /* while blocks */
2096 LOGIF(repeat,"repeat=true");
2099 #ifdef TYPECHECK_STATISTICS
2100 dolog("Typechecker did %4d iterations",count_iterations);
2101 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2102 TYPECHECK_COUNTIF(jsrencountered,stat_typechecked_jsr);
2105 #ifdef TYPECHECK_DEBUG
2106 for (i=0; i<m->basicblockcount; ++i) {
2107 if (m->basicblocks[i].flags != BBDELETED
2108 && m->basicblocks[i].flags != BBUNDEF
2109 && m->basicblocks[i].flags != BBFINISHED
2110 && m->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2111 * some exception handlers,
2114 LOG2("block L%03d has invalid flags after typecheck: %d",
2115 m->basicblocks[i].debug_nr,m->basicblocks[i].flags);
2116 panic("Invalid block flags after typecheck");
2121 /* Reset blocks we never reached */
2122 for (i=0; i<m->basicblockcount; ++i) {
2123 if (m->basicblocks[i].flags == BBTYPECHECK_UNDEF)
2124 m->basicblocks[i].flags = BBFINISHED;
2127 LOGimp("exiting typecheck");
2129 /* just return methodinfo* to signal everything was ok */
2136 #endif /* CACAO_TYPECHECK */
2139 * These are local overrides for various environment variables in Emacs.
2140 * Please do not remove this and leave it at the end of the file, where
2141 * Emacs will automagically detect them.
2142 * ---------------------------------------------------------------------
2145 * indent-tabs-mode: t