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 918 2004-02-08 19:54:52Z edwin $
33 #include "global.h" /* must be here because of CACAO_TYPECHECK */
35 #ifdef CACAO_TYPECHECK
43 #include "toolbox/loging.h"
44 #include "toolbox/memory.h"
46 /****************************************************************************/
48 /****************************************************************************/
50 #ifdef TYPECHECK_VERBOSE_OPT
51 bool typecheckverbose = false;
52 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
57 #ifdef TYPECHECK_VERBOSE
58 #define TYPECHECK_VERBOSE_IMPORTANT
59 #define LOG(str) DOLOG(log_text(str))
60 #define LOG1(str,a) DOLOG(dolog(str,a))
61 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
62 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
63 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
64 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
65 #define LOGFLUSH DOLOG(fflush(get_logfile()))
66 #define LOGNL DOLOG(log_plain("\n"))
67 #define LOGSTR(str) DOLOG(log_plain(str))
68 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
69 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
70 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
71 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
76 #define LOG3(str,a,b,c)
77 #define LOGIF(cond,str)
82 #define LOGSTR1(str,a)
83 #define LOGSTR2(str,a,b)
84 #define LOGSTR3(str,a,b,c)
88 #ifdef TYPECHECK_VERBOSE_IMPORTANT
89 #define LOGimp(str) DOLOG(log_text(str))
90 #define LOGimpSTR(str) DOLOG(log_plain(str))
91 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
94 #define LOGimpSTR(str)
95 #define LOGimpSTRu(utf)
98 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
104 typestack_print(FILE *file,stackptr stack)
107 typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
109 if (stack) fprintf(file," ");
115 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
117 fprintf(file,"Stack: ");
118 typestack_print(file,instack);
119 fprintf(file," Locals:");
120 typevectorset_print(file,localset,size);
125 /****************************************************************************/
127 /****************************************************************************/
129 #ifdef TYPECHECK_DEBUG
130 /*#define TYPECHECK_STATISTICS*/
133 #ifdef TYPECHECK_STATISTICS
134 #define STAT_ITERATIONS 10
135 #define STAT_BLOCKS 10
136 #define STAT_LOCALS 16
138 static int stat_typechecked = 0;
139 static int stat_typechecked_jsr = 0;
140 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
141 static int stat_reached = 0;
142 static int stat_copied = 0;
143 static int stat_merged = 0;
144 static int stat_merging_changed = 0;
145 static int stat_backwards = 0;
146 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
147 static int stat_locals[STAT_LOCALS+1] = { 0 };
148 static int stat_ins = 0;
149 static int stat_ins_field = 0;
150 static int stat_ins_invoke = 0;
151 static int stat_ins_primload = 0;
152 static int stat_ins_aload = 0;
153 static int stat_ins_builtin = 0;
154 static int stat_ins_builtin_gen = 0;
155 static int stat_ins_branch = 0;
156 static int stat_ins_switch = 0;
157 static int stat_ins_unchecked = 0;
158 static int stat_handlers_reached = 0;
160 #define TYPECHECK_COUNT(cnt) (cnt)++
161 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
162 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
164 if ((val) < (limit)) (array)[val]++; \
165 else (array)[limit]++; \
168 static void print_freq(FILE *file,int *array,int limit)
171 for (i=0; i<limit; ++i)
172 fprintf(file," %3d: %8d\n",i,array[i]);
173 fprintf(file," =>%3d: %8d\n",limit,array[limit]);
176 void typecheck_print_statistics(FILE *file) {
177 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
178 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
179 fprintf(file,"reached blocks : %8d\n",stat_reached);
180 fprintf(file,"copied states : %8d\n",stat_copied);
181 fprintf(file,"merged states : %8d\n",stat_merged);
182 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
183 fprintf(file,"backwards branches : %8d\n",stat_backwards);
184 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
185 fprintf(file,"instructions : %8d\n",stat_ins);
186 fprintf(file," field access : %8d\n",stat_ins_field);
187 fprintf(file," invocations : %8d\n",stat_ins_invoke);
188 fprintf(file," load primitive : %8d\n",stat_ins_primload);
189 fprintf(file," load address : %8d\n",stat_ins_aload);
190 fprintf(file," builtins : %8d\n",stat_ins_builtin);
191 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
192 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
193 fprintf(file," branches : %8d\n",stat_ins_branch);
194 fprintf(file," switches : %8d\n",stat_ins_switch);
195 fprintf(file,"iterations used:\n");
196 print_freq(file,stat_iterations,STAT_ITERATIONS);
197 fprintf(file,"basic blocks per method / 10:\n");
198 print_freq(file,stat_blocks,STAT_BLOCKS);
199 fprintf(file,"locals:\n");
200 print_freq(file,stat_locals,STAT_LOCALS);
205 #define TYPECHECK_COUNT(cnt)
206 #define TYPECHECK_COUNTIF(cond,cnt)
207 #define TYPECHECK_COUNT_FREQ(array,val,limit)
210 /****************************************************************************/
211 /* TYPESTACK FUNCTIONS */
212 /****************************************************************************/
214 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
215 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
217 #define TYPESTACK_IS_REFERENCE(sptr) \
218 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
220 #define TYPESTACK_RETURNADDRESSSET(sptr) \
221 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
223 #define RETURNADDRESSSET_SEEK(set,pos) \
224 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
227 typestack_copy(stackptr dst,stackptr y,typevector *selected)
230 typeinfo_retaddr_set *sety;
231 typeinfo_retaddr_set *new;
232 typeinfo_retaddr_set **next;
235 for (;dst; dst=dst->prev, y=y->prev) {
236 if (!y) panic("Stack depth mismatch");
237 if (dst->type != y->type)
238 panic("Stack type mismatch");
239 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
240 if (dst->type == TYPE_ADDRESS) {
241 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
242 /* We copy the returnAddresses from the selected
245 LOG("copying returnAddress");
246 sety = TYPESTACK_RETURNADDRESSSET(y);
248 for (k=0,sel=selected; sel; sel=sel->alt) {
249 LOG1("selected k=%d",sel->k);
254 *next = DNEW(typeinfo_retaddr_set);
255 (*next)->addr = sety->addr;
256 next = &((*next)->alt);
259 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
262 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
266 if (y) panic("Stack depth mismatch");
270 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
272 #ifdef TYPECHECK_DEBUG
273 if (dst->type != TYPE_ADDRESS)
274 panic("Internal error: Storing returnAddress in non-address slot");
277 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
278 for (;loc; loc=loc->alt) {
279 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
281 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
282 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
287 typestack_collapse(stackptr dst)
289 for (; dst; dst = dst->prev) {
290 if (TYPESTACK_IS_RETURNADDRESS(dst))
291 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
296 typestack_merge(stackptr dst,stackptr y)
298 bool changed = false;
299 for (; dst; dst = dst->prev, y=y->prev) {
300 if (!y) panic("Stack depth mismatch");
301 if (dst->type != y->type) panic("Stack type mismatch");
302 if (dst->type == TYPE_ADDRESS) {
303 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
304 /* dst has returnAddress type */
305 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo))
306 panic("Merging returnAddress with reference");
309 /* dst has reference type */
310 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo))
311 panic("Merging reference with returnAddress");
312 changed |= typeinfo_merge(&(dst->typeinfo),&(y->typeinfo));
316 if (y) panic("Stack depth mismatch");
321 typestack_add(stackptr dst,stackptr y,int ky)
323 typeinfo_retaddr_set *setd;
324 typeinfo_retaddr_set *sety;
326 for (; dst; dst = dst->prev, y=y->prev) {
327 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
328 setd = TYPESTACK_RETURNADDRESSSET(dst);
329 sety = TYPESTACK_RETURNADDRESSSET(y);
330 RETURNADDRESSSET_SEEK(sety,ky);
333 setd->alt = DNEW(typeinfo_retaddr_set);
334 setd->alt->addr = sety->addr;
335 setd->alt->alt = NULL;
340 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
342 typestack_separable_with(stackptr a,stackptr b,int kb)
344 typeinfo_retaddr_set *seta;
345 typeinfo_retaddr_set *setb;
347 for (; a; a = a->prev, b = b->prev) {
348 #ifdef TYPECHECK_DEBUG
349 if (!b) panic("Internal error: typestack_separable_from: different depth");
351 if (TYPESTACK_IS_RETURNADDRESS(a)) {
352 #ifdef TYPECHECK_DEBUG
353 if (!TYPESTACK_IS_RETURNADDRESS(b))
354 panic("Internal error: typestack_separable_from: unmergable stacks");
356 seta = TYPESTACK_RETURNADDRESSSET(a);
357 setb = TYPESTACK_RETURNADDRESSSET(b);
358 RETURNADDRESSSET_SEEK(setb,kb);
360 for (;seta;seta=seta->alt)
361 if (seta->addr != setb->addr) return true;
364 #ifdef TYPECHECK_DEBUG
365 if (b) panic("Internal error: typestack_separable_from: different depth");
370 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
372 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
374 typeinfo_retaddr_set *seta;
375 typeinfo_retaddr_set *setb;
377 for (; a; a = a->prev, b = b->prev) {
378 #ifdef TYPECHECK_DEBUG
379 if (!b) panic("Internal error: typestack_separable_from: different depth");
381 if (TYPESTACK_IS_RETURNADDRESS(a)) {
382 #ifdef TYPECHECK_DEBUG
383 if (!TYPESTACK_IS_RETURNADDRESS(b))
384 panic("Internal error: typestack_separable_from: unmergable stacks");
386 seta = TYPESTACK_RETURNADDRESSSET(a);
387 setb = TYPESTACK_RETURNADDRESSSET(b);
388 RETURNADDRESSSET_SEEK(seta,ka);
389 RETURNADDRESSSET_SEEK(setb,kb);
391 if (seta->addr != setb->addr) return true;
394 #ifdef TYPECHECK_DEBUG
395 if (b) panic("Internal error: typestack_separable_from: different depth");
400 /****************************************************************************/
401 /* TYPESTATE FUNCTIONS */
402 /****************************************************************************/
405 typestate_merge(stackptr deststack,typevector *destloc,
406 stackptr ystack,typevector *yloc,
407 int locsize,bool jsrencountered)
409 typevector *dvec,*yvec;
411 bool changed = false;
414 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
415 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
416 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
417 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
420 /* The stack is always merged. If there are returnAddresses on
421 * the stack they are ignored in this step. */
423 changed |= typestack_merge(deststack,ystack);
426 return typevector_merge(destloc,yloc,locsize);
428 for (yvec=yloc; yvec; yvec=yvec->alt) {
431 /* Check if the typestates (deststack,destloc) will be
432 * separable when (ystack,yvec) is added. */
434 if (!typestack_separable_with(deststack,ystack,ky)
435 && !typevectorset_separable_with(destloc,yvec,locsize))
437 /* No, the resulting set won't be separable, thus we
438 * may merge all states in (deststack,destloc) and
441 typestack_collapse(deststack);
442 typevectorset_collapse(destloc,locsize);
443 typevector_merge(destloc,yvec,locsize);
446 /* Yes, the resulting set will be separable. Thus we check
447 * if we may merge (ystack,yvec) with a single state in
448 * (deststack,destloc). */
450 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
451 if (!typestack_separable_from(ystack,ky,deststack,kd)
452 && !typevector_separable_from(yvec,dvec,locsize))
454 /* The typestate (ystack,yvec) is not separable from
455 * (deststack,dvec) by any returnAddress. Thus we may
456 * merge the states. */
458 changed |= typevector_merge(dvec,yvec,locsize);
464 /* The typestate (ystack,yvec) is separable from all typestates
465 * (deststack,destloc). Thus we must add this state to the
468 typestack_add(deststack,ystack,ky);
469 typevectorset_add(destloc,yvec,locsize);
478 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
479 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
489 typestate_reach(void *localbuf,
491 basicblock *destblock,
492 stackptr ystack,typevector *yloc,
493 int locsize,bool jsrencountered)
497 bool changed = false;
499 LOG1("reaching block L%03d",destblock->debug_nr);
500 TYPECHECK_COUNT(stat_reached);
502 destidx = destblock - block;
503 destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
505 /* When branching backwards we have to check for uninitialized objects */
507 if (destblock <= current) {
511 TYPECHECK_COUNT(stat_backwards);
513 for (sp = ystack; sp; sp=sp->prev)
514 if (sp->type == TYPE_ADR &&
515 TYPEINFO_IS_NEWOBJECT(sp->typeinfo))
516 panic("Branching backwards with uninitialized object on stack");
518 for (i=0; i<locsize; ++i)
519 if (yloc->td[i].type == TYPE_ADR &&
520 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
521 panic("Branching backwards with uninitialized object in local variable");
524 if (destblock->flags == BBTYPECHECK_UNDEF) {
525 /* The destblock has never been reached before */
527 TYPECHECK_COUNT(stat_copied);
528 LOG1("block (index %04d) reached first time",destidx);
530 typestack_copy(destblock->instack,ystack,yloc);
531 COPY_TYPEVECTORSET(yloc,destloc,locsize);
535 /* The destblock has already been reached before */
537 TYPECHECK_COUNT(stat_merged);
538 LOG1("block (index %04d) reached before",destidx);
540 changed = typestate_merge(destblock->instack,destloc,
543 TYPECHECK_COUNTIF(changed,stat_merging_changed);
548 destblock->flags = BBTYPECHECK_REACHED;
549 if (destblock <= current) {LOG("REPEAT!"); return true;}
555 * see typestate_reach
558 typestate_ret(void *localbuf,
560 stackptr ystack,typevector *yloc,
561 int retindex,int locsize)
564 typevector *selected;
565 basicblock *destblock;
568 for (yvec=yloc; yvec; ) {
569 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
570 panic("Illegal instruction: RET on non-returnAddress");
572 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
574 selected = typevectorset_select(&yvec,retindex,destblock);
576 repeat |= typestate_reach(localbuf,current,destblock,
577 ystack,selected,locsize,true);
582 /****************************************************************************/
583 /* HELPER FUNCTIONS */
584 /****************************************************************************/
586 /* If a field is checked, definingclass == implementingclass */
588 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass,
591 /* check access rights */
592 if (class != definingclass) {
593 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
597 /* In the cases below, definingclass cannot be an interface */
600 if (definingclass->packagename != class->packagename)
604 if (definingclass->packagename != class->packagename) {
605 if (!builtin_isanysubclass(class,implementingclass))
608 /* For protected access of super class members in another
609 * package the instance must be a subclass of or the same
610 * as the current class. */
611 LOG("protected access into other package");
612 implementingclass = class;
616 if (definingclass != class) {
617 LOG("private access");
622 panic("Invalid access flags");
627 if ((flags & ACC_STATIC) != 0) {
628 LOG("accessing STATIC member with instance");
632 if (implementingclass
633 && !TYPEINFO_IS_NULLTYPE(*instance)
634 && !TYPEINFO_IS_NEWOBJECT(*instance))
636 if (!typeinfo_is_assignable_to_classinfo(instance,
639 LOG("instance not assignable");
641 LOGSTRu(implementingclass->name); LOGNL; LOGFLUSH;
647 if ((flags & ACC_STATIC) == 0) {
648 LOG("accessing non-STATIC member without instance");
656 /****************************************************************************/
657 /* MACROS FOR LOCAL VARIABLE CHECKING */
658 /****************************************************************************/
660 #define INDEX_ONEWORD(num) \
661 do { if((num)<0 || (num)>=validlocals) \
662 panic("Invalid local variable index"); } while (0)
663 #define INDEX_TWOWORD(num) \
664 do { if((num)<0 || ((num)+1)>=validlocals) \
665 panic("Invalid local variable index"); } while (0)
667 #define STORE_ONEWORD(num,type) \
668 do {typevectorset_store(localset,num,type,NULL);} while(0)
670 #define STORE_TWOWORD(num,type) \
671 do {typevectorset_store_twoword(localset,num,type);} while(0)
673 #define CHECK_ONEWORD(num,tp) \
674 do {TYPECHECK_COUNT(stat_ins_primload); \
675 if (jsrencountered) { \
676 if (!typevectorset_checktype(localset,num,tp)) \
677 panic("Variable type mismatch"); \
680 if (localset->td[num].type != tp) \
681 panic("Variable type mismatch"); \
685 #define CHECK_TWOWORD(num,type) \
686 do {TYPECHECK_COUNT(stat_ins_primload); \
687 if (!typevectorset_checktype(localset,num,type)) \
688 panic("Variable type mismatch"); \
691 /****************************************************************************/
692 /* MACROS FOR STACK TYPE CHECKING */
693 /****************************************************************************/
695 /* These macros are for basic typechecks which were not done in stack.c */
697 #define TYPECHECK_STACK(sp,tp) \
698 do { if ((sp)->type != (tp)) \
699 panic("Wrong data type on stack"); } while(0)
701 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
702 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
703 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
704 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
705 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
707 #define TYPECHECK_ARGS1(t1) \
708 do {TYPECHECK_STACK(curstack,t1);} while (0)
709 #define TYPECHECK_ARGS2(t1,t2) \
710 do {TYPECHECK_ARGS1(t1); \
711 TYPECHECK_STACK(curstack->prev,t2);} while (0)
712 #define TYPECHECK_ARGS3(t1,t2,t3) \
713 do {TYPECHECK_ARGS2(t1,t2); \
714 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
716 /****************************************************************************/
718 /****************************************************************************/
720 #define COPYTYPE(source,dest) \
721 {if ((source)->type == TYPE_ADR) \
722 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
724 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
726 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
727 * from the current block (bptr). The types of local variables and
728 * stack slots are propagated to the target block.
730 * bptr.......current block
731 * tbptr......target block
732 * dst........current output stack pointer
733 * numlocals..number of local variables
734 * localset...current local variable vectorset
735 * localbuf...local variable vectorset buffer
736 * jsrencountered...true if a JSR has been seen
738 * repeat.....changed to true if a block before the current
741 #define TYPECHECK_REACH \
743 repeat |= typestate_reach(localbuf,bptr,tbptr,dst, \
744 localset,numlocals,jsrencountered); \
748 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
750 * class........class of the current method
751 * numlocals....number of local variables
752 * localset.....current local variable vectorset
753 * initmethod...true if this is an <init> method
755 #define TYPECHECK_LEAVE \
757 if (initmethod && class != class_java_lang_Object) { \
758 /* check the marker variable */ \
759 LOG("Checking <init> marker"); \
760 if (!typevectorset_checktype(localset,numlocals-1,TYPE_INT))\
761 panic("<init> method does not initialize 'this'"); \
765 /****************************************************************************/
767 /****************************************************************************/
769 #define MAXPARAMS 255
771 /* typecheck is called directly after analyse_stack */
775 int b_count, b_index;
776 stackptr curstack; /* input stack top for current instruction */
777 stackptr srcstack; /* source stack for copying and merging */
778 int opcode; /* current opcode */
779 int i; /* temporary counter */
780 int len; /* for counting instructions, etc. */
781 bool superblockend; /* true if no fallthrough to next block */
782 bool repeat; /* if true, blocks are iterated over again */
783 instruction *iptr; /* pointer to current instruction */
784 basicblock *bptr; /* pointer to current basic block */
785 basicblock *tbptr; /* temporary for target block */
787 int numlocals; /* number of local variables */
788 int validlocals; /* number of valid local variable indices */
789 void *localbuf; /* local variable types for each block start */
790 typevector *localset; /* typevector set for local variables */
791 typevector *lset; /* temporary pointer */
792 typedescriptor *td; /* temporary pointer */
794 typeinfo *savedtypes = NULL; /* saved types of instack slots */
795 typeinfo *savedtypesbuf = NULL; /* reusable buffer for the above */
797 stackelement excstack; /* instack for exception handlers */
799 typedescriptor returntype; /* return type of current method */
800 u1 *ptype; /* parameter types of called method */
801 typeinfo *pinfo; /* parameter typeinfos of called method */
802 int rtype; /* return type of called method */
803 typeinfo rinfo; /* typeinfo for return type of called method */
805 stackptr dst; /* output stack of current instruction */
806 basicblock **tptr; /* pointer into target list of switch instr. */
807 xtable **handlers; /* active exception handlers */
808 classinfo *cls; /* temporary */
809 bool maythrow; /* true if this instruction may throw */
810 static utf *name_init; /* "<init>" */
811 bool initmethod; /* true if this is an "<init>" method */
812 builtin_descriptor *builtindesc; /* temp. descriptor of builtin */
813 bool jsrencountered = false; /* true if we there was a JSR */
815 #ifdef TYPECHECK_STATISTICS
816 int count_iterations = 0;
817 TYPECHECK_COUNT(stat_typechecked);
818 TYPECHECK_COUNT_FREQ(stat_locals,maxlocals,STAT_LOCALS);
819 TYPECHECK_COUNT_FREQ(stat_blocks,block_count/10,STAT_BLOCKS);
822 LOGSTR("\n==============================================================================\n");
823 DOLOG(show_icmd_method());
824 LOGSTR("\n==============================================================================\n");
825 LOGimpSTR("Entering typecheck: ");
826 LOGimpSTRu(method->name);
828 LOGimpSTRu(method->descriptor);
829 LOGimpSTR(" (class ");
830 LOGimpSTRu(method->class->name);
835 name_init = utf_new_char("<init>");
836 initmethod = (method->name == name_init);
838 /* Allocate buffer for method arguments */
840 ptype = DMNEW(u1,MAXPARAMS);
841 pinfo = DMNEW(typeinfo,MAXPARAMS);
843 LOG("Buffer allocated.\n");
845 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
846 b_count = block_count;
848 while (--b_count >= 0) {
849 #ifdef TYPECHECK_DEBUG
850 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
851 && bptr->flags != BBUNDEF)
854 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
855 panic("Internal error: Unexpected block flags in typecheck()");
858 if (bptr->flags >= BBFINISHED) {
859 bptr->flags = BBTYPECHECK_UNDEF;
864 /* The first block is always reached */
865 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
866 block[0].flags = BBTYPECHECK_REACHED;
868 LOG("Blocks reset.\n");
870 /* number of local variables */
872 /* In <init> methods we use an extra local variable to signal if
873 * the 'this' reference has been initialized. */
874 numlocals = maxlocals;
875 validlocals = numlocals;
876 if (initmethod) numlocals++;
878 /* allocate the buffers for local variables */
879 localbuf = DMNEW_TYPEVECTOR(block_count+1, numlocals);
880 localset = MGET_TYPEVECTOR(localbuf,block_count,numlocals);
882 LOG("Variable buffer allocated.\n");
884 /* allocate the buffer of active exception handlers */
885 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
887 /* initialize the variable types of the first block */
888 /* to the types of the arguments */
889 lset = MGET_TYPEVECTOR(localbuf,0,numlocals);
895 /* if this is an instance method initialize the "this" ref type */
896 if (!(method->flags & ACC_STATIC)) {
898 panic("Not enough local variables for method arguments");
899 td->type = TYPE_ADDRESS;
901 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
903 TYPEINFO_INIT_CLASSINFO(td->info,class);
908 LOG("'this' argument set.\n");
910 /* the rest of the arguments and the return type */
911 i = typedescriptors_init_from_method_args(td,method->descriptor,
913 true, /* two word types use two slots */
916 i = numlocals - (td - lset->td);
918 td->type = TYPE_VOID;
922 LOG("Arguments set.\n");
924 /* initialize the input stack of exception handlers */
925 excstack.prev = NULL;
926 excstack.type = TYPE_ADR;
927 TYPEINFO_INIT_CLASSINFO(excstack.typeinfo,
928 class_java_lang_Throwable); /* changed later */
930 LOG("Exception handler stacks set.\n");
932 /* loop while there are still blocks to be checked */
934 TYPECHECK_COUNT(count_iterations);
938 b_count = block_count;
941 while (--b_count >= 0) {
942 LOGSTR1("---- BLOCK %04d, ",bptr-block);
943 LOGSTR1("blockflags: %d\n",bptr->flags);
946 if (bptr->flags == BBTYPECHECK_REACHED) {
947 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
950 superblockend = false;
951 bptr->flags = BBFINISHED;
952 b_index = bptr - block;
954 /* init stack at the start of this block */
955 curstack = bptr->instack;
957 /* determine the active exception handlers for this block */
958 /* XXX could use a faster algorithm with sorted lists or
961 for (i=0; i<method->exceptiontablelength; ++i) {
962 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
963 LOG1("active handler L%03d",extable[i].handler->debug_nr);
964 handlers[len++] = extable + i;
967 handlers[len] = NULL;
969 /* init variable types at the start of this block */
970 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
973 for (i=0; i<numlocals; ++i)
974 if (localset->td[i].type == TYPE_ADR
975 && TYPEINFO_IS_NEWOBJECT(localset->td[i].info))
976 panic("Uninitialized object in local variable inside try block");
978 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
981 /* loop over the instructions */
985 TYPECHECK_COUNT(stat_ins);
986 DOLOG(show_icmd(iptr,false)); LOGNL; LOGFLUSH;
994 /****************************************/
995 /* STACK MANIPULATIONS */
997 /* We just need to copy the typeinfo */
998 /* for slots containing addresses. */
1000 /* XXX We assume that the destination stack
1001 * slots were continuously allocated in
1002 * memory. (The current implementation in
1007 COPYTYPE(curstack,dst);
1011 COPYTYPE(curstack,dst);
1012 COPYTYPE(curstack,dst-2);
1013 COPYTYPE(curstack->prev,dst-1);
1017 COPYTYPE(curstack,dst);
1018 COPYTYPE(curstack,dst-3);
1019 COPYTYPE(curstack->prev,dst-1);
1020 COPYTYPE(curstack->prev->prev,dst-2);
1024 COPYTYPE(curstack,dst);
1025 COPYTYPE(curstack->prev,dst-1);
1029 COPYTYPE(curstack,dst);
1030 COPYTYPE(curstack->prev,dst-1);
1031 COPYTYPE(curstack,dst-3);
1032 COPYTYPE(curstack->prev,dst-4);
1033 COPYTYPE(curstack->prev->prev,dst-2);
1037 COPYTYPE(curstack,dst);
1038 COPYTYPE(curstack->prev,dst-1);
1039 COPYTYPE(curstack,dst-4);
1040 COPYTYPE(curstack->prev,dst-5);
1041 COPYTYPE(curstack->prev->prev,dst-2);
1042 COPYTYPE(curstack->prev->prev->prev,dst-3);
1046 COPYTYPE(curstack,dst-1);
1047 COPYTYPE(curstack->prev,dst);
1050 /****************************************/
1051 /* PRIMITIVE VARIABLE ACCESS */
1053 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1054 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1055 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1056 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1057 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1059 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1060 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1061 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1062 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1064 /****************************************/
1065 /* LOADING ADDRESS FROM VARIABLE */
1068 TYPECHECK_COUNT(stat_ins_aload);
1070 /* loading a returnAddress is not allowed */
1071 if (jsrencountered) {
1072 if (!typevectorset_checkreference(localset,iptr->op1))
1073 panic("illegal instruction: ALOAD loading non-reference");
1075 typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
1078 if (!TYPEDESC_IS_REFERENCE(localset->td[iptr->op1]))
1079 panic("illegal instruction: ALOAD loading non-reference");
1080 TYPEINFO_COPY(localset->td[iptr->op1].info,dst->typeinfo);
1084 /****************************************/
1085 /* STORING ADDRESS TO VARIABLE */
1089 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1090 panic("Storing uninitialized object in local variable inside try block");
1092 if (TYPESTACK_IS_RETURNADDRESS(curstack))
1093 typevectorset_store_retaddr(localset,iptr->op1,&(curstack->typeinfo));
1095 typevectorset_store(localset,iptr->op1,TYPE_ADDRESS,
1096 &(curstack->typeinfo));
1099 /****************************************/
1100 /* LOADING ADDRESS FROM ARRAY */
1103 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1104 panic("illegal instruction: AALOAD on non-reference array");
1106 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1110 /****************************************/
1114 TYPECHECK_COUNT(stat_ins_field);
1115 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1116 panic("illegal instruction: PUTFIELD on non-reference");
1117 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo))
1118 panic("illegal instruction: PUTFIELD on array");
1120 /* check if the value is assignable to the field */
1122 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1124 if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1126 && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1128 /* uninitialized "this" instance */
1129 if (fi->class != class || (fi->flags & ACC_STATIC) != 0)
1130 panic("Setting unaccessible field in uninitialized object");
1133 panic("PUTFIELD on uninitialized object");
1137 if (!is_accessible(fi->flags,fi->class,fi->class,
1138 &(curstack->prev->typeinfo)))
1139 panic("PUTFIELD: field is not accessible");
1142 if (curstack->type != fi->type)
1143 panic("PUTFIELD type mismatch");
1144 if (fi->type == TYPE_ADR) {
1145 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1146 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1148 panic("PUTFIELD reference type not assignable");
1154 case ICMD_PUTSTATIC:
1155 TYPECHECK_COUNT(stat_ins_field);
1156 /* check if the value is assignable to the field */
1158 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1160 if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1161 panic("PUTSTATIC: field is not accessible");
1163 if (curstack->type != fi->type)
1164 panic("PUTSTATIC type mismatch");
1165 if (fi->type == TYPE_ADR) {
1166 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1167 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1169 panic("PUTSTATIC reference type not assignable");
1176 TYPECHECK_COUNT(stat_ins_field);
1177 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1178 panic("illegal instruction: GETFIELD on non-reference");
1179 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1180 panic("illegal instruction: GETFIELD on array");
1183 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1185 if (!is_accessible(fi->flags,fi->class,fi->class,
1186 &(curstack->typeinfo)))
1187 panic("GETFIELD: field is not accessible");
1189 if (dst->type == TYPE_ADR) {
1190 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1196 case ICMD_GETSTATIC:
1197 TYPECHECK_COUNT(stat_ins_field);
1199 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1201 if (!is_accessible(fi->flags,fi->class,fi->class,NULL))
1202 panic("GETSTATIC: field is not accessible");
1204 if (dst->type == TYPE_ADR) {
1205 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1211 /****************************************/
1212 /* PRIMITIVE ARRAY ACCESS */
1214 case ICMD_ARRAYLENGTH:
1215 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo)
1216 && curstack->typeinfo.typeclass != pseudo_class_Arraystub)
1217 panic("illegal instruction: ARRAYLENGTH on non-array");
1222 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1223 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1224 panic("Array type mismatch");
1228 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1229 panic("Array type mismatch");
1233 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1234 panic("Array type mismatch");
1238 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1239 panic("Array type mismatch");
1243 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1244 panic("Array type mismatch");
1248 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1249 panic("Array type mismatch");
1253 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1254 panic("Array type mismatch");
1259 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1260 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1261 panic("Array type mismatch");
1265 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1266 panic("Array type mismatch");
1270 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1271 panic("Array type mismatch");
1275 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1276 panic("Array type mismatch");
1280 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1281 panic("Array type mismatch");
1285 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1286 panic("Array type mismatch");
1290 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1291 panic("Array type mismatch");
1295 /****************************************/
1296 /* ADDRESS CONSTANTS */
1299 if (iptr->val.a == NULL)
1300 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1302 /* string constants (or constant for builtin function) */
1303 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1306 /****************************************/
1307 /* CHECKCAST AND INSTANCEOF */
1309 case ICMD_CHECKCAST:
1310 TYPECHECK_ADR(curstack);
1311 /* returnAddress is not allowed */
1312 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1313 panic("Illegal instruction: CHECKCAST on non-reference");
1315 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1319 case ICMD_INSTANCEOF:
1320 TYPECHECK_ADR(curstack);
1321 /* returnAddress is not allowed */
1322 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1323 panic("Illegal instruction: INSTANCEOF on non-reference");
1326 /****************************************/
1327 /* BRANCH INSTRUCTIONS */
1330 superblockend = true;
1333 case ICMD_IFNONNULL:
1340 case ICMD_IF_ICMPEQ:
1341 case ICMD_IF_ICMPNE:
1342 case ICMD_IF_ICMPLT:
1343 case ICMD_IF_ICMPGE:
1344 case ICMD_IF_ICMPGT:
1345 case ICMD_IF_ICMPLE:
1346 case ICMD_IF_ACMPEQ:
1347 case ICMD_IF_ACMPNE:
1354 case ICMD_IF_LCMPEQ:
1355 case ICMD_IF_LCMPNE:
1356 case ICMD_IF_LCMPLT:
1357 case ICMD_IF_LCMPGE:
1358 case ICMD_IF_LCMPGT:
1359 case ICMD_IF_LCMPLE:
1360 TYPECHECK_COUNT(stat_ins_branch);
1361 tbptr = (basicblock *) iptr->target;
1363 /* propagate stack and variables to the target block */
1367 /****************************************/
1370 case ICMD_TABLESWITCH:
1371 TYPECHECK_COUNT(stat_ins_switch);
1373 s4 *s4ptr = iptr->val.a;
1374 s4ptr++; /* skip default */
1375 i = *s4ptr++; /* low */
1376 i = *s4ptr++ - i + 2; /* +1 for default target */
1378 goto switch_instruction_tail;
1380 case ICMD_LOOKUPSWITCH:
1381 TYPECHECK_COUNT(stat_ins_switch);
1383 s4 *s4ptr = iptr->val.a;
1384 s4ptr++; /* skip default */
1385 i = *s4ptr++ + 1; /* count +1 for default */
1387 switch_instruction_tail:
1388 tptr = (basicblock **)iptr->target;
1392 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1396 superblockend = true;
1399 /****************************************/
1400 /* RETURNS AND THROW */
1403 if (!typeinfo_is_assignable_to_classinfo(
1404 &curstack->typeinfo,class_java_lang_Throwable))
1405 panic("illegal instruction: ATHROW on non-Throwable");
1406 superblockend = true;
1411 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1412 panic("illegal instruction: ARETURN on non-reference");
1414 if (returntype.type != TYPE_ADDRESS
1415 || !typeinfo_is_assignable(&curstack->typeinfo,&(returntype.info)))
1416 panic("Return type mismatch");
1420 if (returntype.type != TYPE_INT) panic("Return type mismatch");
1424 if (returntype.type != TYPE_LONG) panic("Return type mismatch");
1428 if (returntype.type != TYPE_FLOAT) panic("Return type mismatch");
1432 if (returntype.type != TYPE_DOUBLE) panic("Return type mismatch");
1436 if (returntype.type != TYPE_VOID) panic("Return type mismatch");
1439 superblockend = true;
1443 /****************************************/
1444 /* SUBROUTINE INSTRUCTIONS */
1448 jsrencountered = true;
1450 /* This is a dirty hack. It is needed
1451 * because of the special handling of
1452 * ICMD_JSR in stack.c
1454 dst = (stackptr) iptr->val.a;
1456 tbptr = (basicblock *) iptr->target;
1457 if (bptr+1 == last_block)
1458 panic("Illegal instruction: JSR at end of bytecode");
1459 typestack_put_retaddr(dst,bptr+1,localset);
1460 repeat |= typestate_reach(localbuf,bptr,tbptr,dst,
1461 localset,numlocals,true);
1463 superblockend = true;
1467 /* check returnAddress variable */
1468 if (!typevectorset_checkretaddr(localset,iptr->op1))
1469 panic("illegal instruction: RET using non-returnAddress variable");
1471 repeat |= typestate_ret(localbuf,bptr,curstack,
1472 localset,iptr->op1,numlocals);
1474 superblockend = true;
1477 /****************************************/
1480 case ICMD_INVOKEVIRTUAL:
1481 case ICMD_INVOKESPECIAL:
1482 case ICMD_INVOKESTATIC:
1483 case ICMD_INVOKEINTERFACE:
1484 TYPECHECK_COUNT(stat_ins_invoke);
1486 methodinfo *mi = (methodinfo*) iptr->val.a;
1487 bool specialmethod = (mi->name->text[0] == '<');
1488 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1490 classinfo *initclass;
1492 if (specialmethod && !callinginit)
1493 panic("Invalid invocation of special method");
1495 if (opcode == ICMD_INVOKESPECIAL) {
1496 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1498 /* (If callinginit the class is checked later.) */
1500 if (!builtin_isanysubclass(class,mi->class))
1501 panic("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1505 /* fetch parameter types and return type */
1507 if (opcode != ICMD_INVOKESTATIC) {
1508 ptype[0] = TYPE_ADR;
1509 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1512 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1516 /* check parameter types */
1517 srcstack = curstack;
1518 i = mi->paramcount; /* number of parameters including 'this'*/
1521 if (srcstack->type != ptype[i])
1522 panic("Parameter type mismatch in method invocation");
1523 if (srcstack->type == TYPE_ADR) {
1524 LOGINFO(&(srcstack->typeinfo));
1526 if (i==0 && callinginit)
1528 /* first argument to <init> method */
1529 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1530 panic("Calling <init> on initialized object");
1532 /* get the address of the NEW instruction */
1533 LOGINFO(&(srcstack->typeinfo));
1534 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1535 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1536 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1539 /* (This is checked below.) */
1540 /* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1541 /* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1542 /* panic("Parameter reference type mismatch in <init> invocation"); */
1545 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1546 panic("Parameter reference type mismatch in method invocation");
1551 if (i) srcstack = srcstack->prev;
1554 /* XXX We should resolve the method and pass its
1555 * class as implementingclass to is_accessible. */
1556 if (!is_accessible(mi->flags,mi->class,NULL,
1557 (opcode == ICMD_INVOKESTATIC) ? NULL
1558 : &(srcstack->typeinfo)))
1559 panic("Invoking unaccessible method");
1561 LOG("checking return type");
1562 if (rtype != TYPE_VOID) {
1563 if (rtype != dst->type)
1564 panic("Return type mismatch in method invocation");
1565 TYPEINFO_COPY(rinfo,dst->typeinfo);
1569 LOG("replacing uninitialized object");
1570 /* replace uninitialized object type on stack */
1573 if (srcstack->type == TYPE_ADR
1574 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1575 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1577 LOG("replacing uninitialized type on stack");
1579 /* If this stackslot is in the instack of
1580 * this basic block we must save the type(s)
1581 * we are going to replace.
1583 if (srcstack <= bptr->instack && !savedtypes)
1587 LOG("saving input stack types");
1588 if (!savedtypesbuf) {
1589 LOG("allocating savedtypes buffer");
1590 savedtypesbuf = DMNEW(typeinfo,maxstack);
1592 ti = savedtypes = savedtypesbuf;
1593 for (sp=bptr->instack; sp; sp=sp->prev, ti++)
1594 TYPEINFO_COPY(sp->typeinfo,*ti);
1597 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1599 srcstack = srcstack->prev;
1601 /* replace uninitialized object type in locals */
1602 typevectorset_init_object(localset,ins,initclass,numlocals);
1604 /* initializing the 'this' reference? */
1606 #ifdef TYPECHECK_DEBUG
1608 panic("Internal error: calling <init> on this in non-<init> method.");
1610 /* must be <init> of current class or direct superclass */
1611 if (mi->class != class && mi->class != class->super)
1612 panic("<init> calling <init> of the wrong class");
1614 /* set our marker variable to type int */
1615 LOG("setting <init> marker");
1616 typevectorset_store(localset,numlocals-1,TYPE_INT,NULL);
1619 /* initializing an instance created with NEW */
1620 /* XXX is this strictness ok? */
1621 if (mi->class != initclass)
1622 panic("Calling <init> method of the wrong class");
1629 case ICMD_MULTIANEWARRAY:
1632 arraydescriptor *desc;
1634 /* check the array lengths on the stack */
1636 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1637 srcstack = curstack;
1640 panic("MULTIANEWARRAY missing array length");
1641 if (srcstack->type != TYPE_INT)
1642 panic("MULTIANEWARRAY using non-int as array length");
1643 srcstack = srcstack->prev;
1646 /* check array descriptor */
1647 arrayvftbl = (vftbl*) iptr[0].val.a;
1649 panic("MULTIANEWARRAY with unlinked class");
1650 if ((desc = arrayvftbl->arraydesc) == NULL)
1651 panic("MULTIANEWARRAY with non-array class");
1652 if (desc->dimension < iptr[0].op1)
1653 panic("MULTIANEWARRAY dimension to high");
1655 /* set the array type of the result */
1656 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1662 TYPECHECK_COUNT(stat_ins_builtin);
1663 if (ISBUILTIN(BUILTIN_aastore)) {
1664 TYPECHECK_ADR(curstack);
1665 TYPECHECK_INT(curstack->prev);
1666 TYPECHECK_ADR(curstack->prev->prev);
1667 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1668 panic("illegal instruction: AASTORE to non-reference array");
1671 /* XXX put these checks in a function */
1672 TYPECHECK_COUNT(stat_ins_builtin_gen);
1673 builtindesc = builtin_desc;
1674 while (builtindesc->opcode && builtindesc->builtin
1675 != (functionptr) iptr->val.a) builtindesc++;
1676 if (!builtindesc->opcode) {
1677 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1678 panic("Internal error: builtin not found in table");
1680 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1686 TYPECHECK_COUNT(stat_ins_builtin);
1687 if (ISBUILTIN(BUILTIN_newarray))
1690 TYPECHECK_INT(curstack->prev);
1691 if (iptr[-1].opc != ICMD_ACONST)
1692 panic("illegal instruction: builtin_newarray without classinfo");
1693 vft = (vftbl *)iptr[-1].val.a;
1695 panic("ANEWARRAY with unlinked class");
1696 if (!vft->arraydesc)
1697 panic("ANEWARRAY with non-array class");
1698 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1700 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1703 TYPECHECK_ADR(curstack->prev);
1704 if (iptr[-1].opc != ICMD_ACONST)
1705 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1706 vft = (vftbl *)iptr[-1].val.a;
1708 panic("INSTANCEOF with unlinked class");
1709 if (!vft->arraydesc)
1710 panic("internal error: builtin_arrayinstanceof with non-array class");
1712 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1714 TYPECHECK_ADR(curstack->prev);
1715 if (iptr[-1].opc != ICMD_ACONST)
1716 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1717 vft = (vftbl *)iptr[-1].val.a;
1719 panic("CHECKCAST with unlinked class");
1720 if (!vft->arraydesc)
1721 panic("internal error: builtin_checkarraycast with non-array class");
1722 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1725 TYPECHECK_COUNT(stat_ins_builtin_gen);
1726 builtindesc = builtin_desc;
1727 while (builtindesc->opcode && builtindesc->builtin
1728 != (functionptr) iptr->val.a) builtindesc++;
1729 if (!builtindesc->opcode) {
1730 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1731 panic("Internal error: builtin not found in table");
1733 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1739 TYPECHECK_COUNT(stat_ins_builtin);
1740 if (ISBUILTIN(BUILTIN_new)) {
1742 if (iptr[-1].opc != ICMD_ACONST)
1743 panic("illegal instruction: builtin_new without classinfo");
1744 cls = (classinfo *) iptr[-1].val.a;
1746 panic("Internal error: NEW with unlinked class");
1747 /* The following check also forbids array classes and interfaces: */
1748 if ((cls->flags & ACC_ABSTRACT) != 0)
1749 panic("Invalid instruction: NEW creating instance of abstract class");
1750 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1752 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1753 TYPECHECK_INT(curstack);
1754 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1756 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1757 TYPECHECK_INT(curstack);
1758 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1760 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1761 TYPECHECK_INT(curstack);
1762 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1764 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1765 TYPECHECK_INT(curstack);
1766 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1768 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1769 TYPECHECK_INT(curstack);
1770 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1772 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1773 TYPECHECK_INT(curstack);
1774 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1776 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1777 TYPECHECK_INT(curstack);
1778 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1780 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1781 TYPECHECK_INT(curstack);
1782 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1785 TYPECHECK_COUNT(stat_ins_builtin_gen);
1786 builtindesc = builtin_desc;
1787 while (builtindesc->opcode && builtindesc->builtin
1788 != (functionptr) iptr->val.a) builtindesc++;
1789 if (!builtindesc->opcode) {
1790 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1791 panic("Internal error: builtin not found in table");
1793 TYPECHECK_ARGS1(builtindesc->type_s1);
1798 /****************************************/
1799 /* SIMPLE EXCEPTION THROWING TESTS */
1801 case ICMD_CHECKASIZE:
1802 /* The argument to CHECKASIZE is typechecked by
1803 * typechecking the array creation instructions. */
1806 case ICMD_NULLCHECKPOP:
1807 /* NULLCHECKPOP just requires that the stack top
1808 * is an address. This is checked in stack.c */
1813 /****************************************/
1814 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1815 /* REPLACED BY OTHER OPCODES */
1817 #ifdef TYPECHECK_DEBUG
1820 case ICMD_ANEWARRAY:
1821 case ICMD_MONITORENTER:
1822 case ICMD_MONITOREXIT:
1824 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1825 LOG("Should have been converted to builtin function call.");
1826 panic("Internal error: unexpected instruction encountered");
1829 case ICMD_READONLY_ARG:
1830 case ICMD_CLEAR_ARGREN:
1831 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1832 LOG("Should have been replaced in stack.c.");
1833 panic("Internal error: unexpected pseudo instruction encountered");
1837 /****************************************/
1838 /* UNCHECKED OPERATIONS */
1840 /*********************************************
1841 * Instructions below...
1842 * *) don't operate on local variables,
1843 * *) don't operate on references,
1844 * *) don't operate on returnAddresses.
1846 * (These instructions are typechecked in
1848 ********************************************/
1850 /* Instructions which may throw a runtime exception: */
1860 /* Instructions which never throw a runtime exception: */
1861 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
1871 case ICMD_IFEQ_ICONST:
1872 case ICMD_IFNE_ICONST:
1873 case ICMD_IFLT_ICONST:
1874 case ICMD_IFGE_ICONST:
1875 case ICMD_IFGT_ICONST:
1876 case ICMD_IFLE_ICONST:
1877 case ICMD_ELSE_ICONST:
1899 case ICMD_IREM0X10001:
1900 case ICMD_LREM0X10001:
1903 case ICMD_IADDCONST:
1904 case ICMD_ISUBCONST:
1905 case ICMD_IMULCONST:
1906 case ICMD_IANDCONST:
1908 case ICMD_IXORCONST:
1909 case ICMD_ISHLCONST:
1910 case ICMD_ISHRCONST:
1911 case ICMD_IUSHRCONST:
1913 case ICMD_LADDCONST:
1914 case ICMD_LSUBCONST:
1915 case ICMD_LMULCONST:
1916 case ICMD_LANDCONST:
1918 case ICMD_LXORCONST:
1919 case ICMD_LSHLCONST:
1920 case ICMD_LSHRCONST:
1921 case ICMD_LUSHRCONST:
1938 case ICMD_INT2SHORT:
1941 case ICMD_LCMPCONST:
1960 TYPECHECK_COUNT(stat_ins_unchecked);
1963 /****************************************/
1966 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1967 panic("Missing ICMD code during typecheck");
1971 /* the output of this instruction becomes the current stack */
1974 /* reach exception handlers for this instruction */
1976 LOG("reaching exception handlers");
1978 while (handlers[i]) {
1979 TYPECHECK_COUNT(stat_handlers_reached);
1980 cls = handlers[i]->catchtype;
1981 excstack.typeinfo.typeclass = (cls) ? cls
1982 : class_java_lang_Throwable;
1983 repeat |= typestate_reach(localbuf,bptr,
1984 handlers[i]->handler,
1993 } /* while instructions */
1995 LOG("instructions done");
1996 LOGSTR("RESULT=> ");
1997 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
2000 /* propagate stack and variables to the following block */
2001 if (!superblockend) {
2002 LOG("reaching following block");
2004 while (tbptr->flags == BBDELETED) {
2006 #ifdef TYPECHECK_DEBUG
2007 if ((tbptr-block) >= block_count)
2008 panic("Control flow falls off the last block");
2014 /* We may have to restore the types of the instack slots. They
2015 * have been saved if an <init> call inside the block has
2016 * modified the instack types. (see INVOKESPECIAL) */
2019 typeinfo *ti = savedtypes;
2021 LOG("restoring saved instack types");
2022 for (sp=bptr->instack; sp; sp=sp->prev, ti++) {
2023 if (sp->type == TYPE_ADR && TYPEINFO_IS_NEWOBJECT(*ti))
2024 TYPEINFO_COPY(*ti,sp->typeinfo);
2029 } /* if block has to be checked */
2031 } /* while blocks */
2033 LOGIF(repeat,"repeat=true");
2036 #ifdef TYPECHECK_STATISTICS
2037 dolog("Typechecker did %4d iterations",count_iterations);
2038 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2039 TYPECHECK_COUNTIF(jsrencountered,stat_typechecked_jsr);
2042 #ifdef TYPECHECK_DEBUG
2043 for (i=0; i<block_count; ++i) {
2044 if (block[i].flags != BBDELETED
2045 && block[i].flags != BBUNDEF
2046 && block[i].flags != BBFINISHED
2047 && block[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2048 * some exception handlers,
2051 LOG2("block L%03d has invalid flags after typecheck: %d",
2052 block[i].debug_nr,block[i].flags);
2053 panic("Invalid block flags after typecheck");
2058 /* Reset blocks we never reached */
2059 for (i=0; i<block_count; ++i) {
2060 if (block[i].flags == BBTYPECHECK_UNDEF)
2061 block[i].flags = BBFINISHED;
2064 LOGimp("exiting typecheck");
2069 #endif /* CACAO_TYPECHECK */
2072 * These are local overrides for various environment variables in Emacs.
2073 * Please do not remove this and leave it at the end of the file, where
2074 * Emacs will automagically detect them.
2075 * ---------------------------------------------------------------------
2078 * indent-tabs-mode: t