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 1067 2004-05-18 10:25:51Z stefan $
33 #include "global.h" /* must be here because of CACAO_TYPECHECK */
35 #ifdef CACAO_TYPECHECK
44 #include "toolbox/logging.h"
45 #include "toolbox/memory.h"
47 /****************************************************************************/
49 /****************************************************************************/
51 #ifdef TYPECHECK_VERBOSE_OPT
52 bool typecheckverbose = false;
53 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
58 #ifdef TYPECHECK_VERBOSE
59 #define TYPECHECK_VERBOSE_IMPORTANT
60 #define LOG(str) DOLOG(log_text(str))
61 #define LOG1(str,a) DOLOG(dolog(str,a))
62 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
63 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
64 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
65 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
66 #define LOGFLUSH DOLOG(fflush(get_logfile()))
67 #define LOGNL DOLOG(log_plain("\n"))
68 #define LOGSTR(str) DOLOG(log_plain(str))
69 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
70 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
71 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
72 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
77 #define LOG3(str,a,b,c)
78 #define LOGIF(cond,str)
83 #define LOGSTR1(str,a)
84 #define LOGSTR2(str,a,b)
85 #define LOGSTR3(str,a,b,c)
89 #ifdef TYPECHECK_VERBOSE_IMPORTANT
90 #define LOGimp(str) DOLOG(log_text(str))
91 #define LOGimpSTR(str) DOLOG(log_plain(str))
92 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
95 #define LOGimpSTR(str)
96 #define LOGimpSTRu(utf)
99 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
105 typestack_print(FILE *file,stackptr stack)
108 typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
110 if (stack) fprintf(file," ");
116 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
118 fprintf(file,"Stack: ");
119 typestack_print(file,instack);
120 fprintf(file," Locals:");
121 typevectorset_print(file,localset,size);
126 /****************************************************************************/
128 /****************************************************************************/
130 #ifdef TYPECHECK_DEBUG
131 /*#define TYPECHECK_STATISTICS*/
134 #ifdef TYPECHECK_STATISTICS
135 #define STAT_ITERATIONS 10
136 #define STAT_BLOCKS 10
137 #define STAT_LOCALS 16
139 static int stat_typechecked = 0;
140 static int stat_typechecked_jsr = 0;
141 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
142 static int stat_reached = 0;
143 static int stat_copied = 0;
144 static int stat_merged = 0;
145 static int stat_merging_changed = 0;
146 static int stat_backwards = 0;
147 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
148 static int stat_locals[STAT_LOCALS+1] = { 0 };
149 static int stat_ins = 0;
150 static int stat_ins_field = 0;
151 static int stat_ins_invoke = 0;
152 static int stat_ins_primload = 0;
153 static int stat_ins_aload = 0;
154 static int stat_ins_builtin = 0;
155 static int stat_ins_builtin_gen = 0;
156 static int stat_ins_branch = 0;
157 static int stat_ins_switch = 0;
158 static int stat_ins_unchecked = 0;
159 static int stat_handlers_reached = 0;
160 static int stat_savedstack = 0;
162 #define TYPECHECK_COUNT(cnt) (cnt)++
163 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
164 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
166 if ((val) < (limit)) (array)[val]++; \
167 else (array)[limit]++; \
170 static void print_freq(FILE *file,int *array,int limit)
173 for (i=0; i<limit; ++i)
174 fprintf(file," %3d: %8d\n",i,array[i]);
175 fprintf(file," =>%3d: %8d\n",limit,array[limit]);
178 void typecheck_print_statistics(FILE *file) {
179 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
180 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
181 fprintf(file,"reached blocks : %8d\n",stat_reached);
182 fprintf(file,"copied states : %8d\n",stat_copied);
183 fprintf(file,"merged states : %8d\n",stat_merged);
184 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
185 fprintf(file,"backwards branches : %8d\n",stat_backwards);
186 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
187 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
188 fprintf(file,"instructions : %8d\n",stat_ins);
189 fprintf(file," field access : %8d\n",stat_ins_field);
190 fprintf(file," invocations : %8d\n",stat_ins_invoke);
191 fprintf(file," load primitive : %8d\n",stat_ins_primload);
192 fprintf(file," load address : %8d\n",stat_ins_aload);
193 fprintf(file," builtins : %8d\n",stat_ins_builtin);
194 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
195 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
196 fprintf(file," branches : %8d\n",stat_ins_branch);
197 fprintf(file," switches : %8d\n",stat_ins_switch);
198 fprintf(file,"iterations used:\n");
199 print_freq(file,stat_iterations,STAT_ITERATIONS);
200 fprintf(file,"basic blocks per method / 10:\n");
201 print_freq(file,stat_blocks,STAT_BLOCKS);
202 fprintf(file,"locals:\n");
203 print_freq(file,stat_locals,STAT_LOCALS);
208 #define TYPECHECK_COUNT(cnt)
209 #define TYPECHECK_COUNTIF(cond,cnt)
210 #define TYPECHECK_COUNT_FREQ(array,val,limit)
213 /****************************************************************************/
214 /* TYPESTACK FUNCTIONS */
215 /****************************************************************************/
217 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
218 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
220 #define TYPESTACK_IS_REFERENCE(sptr) \
221 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
223 #define TYPESTACK_RETURNADDRESSSET(sptr) \
224 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
226 #define RETURNADDRESSSET_SEEK(set,pos) \
227 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
229 #define TYPESTACK_COPY(sp,copy) \
230 do {for(; sp; sp=sp->prev, copy=copy->prev) { \
231 copy->type = sp->type; \
232 TYPEINFO_COPY(sp->typeinfo,copy->typeinfo); \
236 typestack_copy(stackptr dst,stackptr y,typevector *selected)
239 typeinfo_retaddr_set *sety;
240 typeinfo_retaddr_set *new;
241 typeinfo_retaddr_set **next;
244 for (;dst; dst=dst->prev, y=y->prev) {
245 if (!y) panic("Stack depth mismatch");
246 if (dst->type != y->type)
247 panic("Stack type mismatch");
248 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
249 if (dst->type == TYPE_ADDRESS) {
250 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
251 /* We copy the returnAddresses from the selected
254 LOG("copying returnAddress");
255 sety = TYPESTACK_RETURNADDRESSSET(y);
257 for (k=0,sel=selected; sel; sel=sel->alt) {
258 LOG1("selected k=%d",sel->k);
263 *next = DNEW(typeinfo_retaddr_set);
264 (*next)->addr = sety->addr;
265 next = &((*next)->alt);
268 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
271 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
275 if (y) panic("Stack depth mismatch");
279 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
281 #ifdef TYPECHECK_DEBUG
282 if (dst->type != TYPE_ADDRESS)
283 panic("Internal error: Storing returnAddress in non-address slot");
286 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
287 for (;loc; loc=loc->alt) {
288 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
290 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
291 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
296 typestack_collapse(stackptr dst)
298 for (; dst; dst = dst->prev) {
299 if (TYPESTACK_IS_RETURNADDRESS(dst))
300 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
305 typestack_merge(stackptr dst,stackptr y)
307 bool changed = false;
308 for (; dst; dst = dst->prev, y=y->prev) {
309 if (!y) panic("Stack depth mismatch");
310 if (dst->type != y->type) panic("Stack type mismatch");
311 if (dst->type == TYPE_ADDRESS) {
312 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
313 /* dst has returnAddress type */
314 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo))
315 panic("Merging returnAddress with reference");
318 /* dst has reference type */
319 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo))
320 panic("Merging reference with returnAddress");
321 changed |= typeinfo_merge(&(dst->typeinfo),&(y->typeinfo));
325 if (y) panic("Stack depth mismatch");
330 typestack_add(stackptr dst,stackptr y,int ky)
332 typeinfo_retaddr_set *setd;
333 typeinfo_retaddr_set *sety;
335 for (; dst; dst = dst->prev, y=y->prev) {
336 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
337 setd = TYPESTACK_RETURNADDRESSSET(dst);
338 sety = TYPESTACK_RETURNADDRESSSET(y);
339 RETURNADDRESSSET_SEEK(sety,ky);
342 setd->alt = DNEW(typeinfo_retaddr_set);
343 setd->alt->addr = sety->addr;
344 setd->alt->alt = NULL;
349 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
351 typestack_separable_with(stackptr a,stackptr b,int kb)
353 typeinfo_retaddr_set *seta;
354 typeinfo_retaddr_set *setb;
356 for (; a; a = a->prev, b = b->prev) {
357 #ifdef TYPECHECK_DEBUG
358 if (!b) panic("Internal error: typestack_separable_from: different depth");
360 if (TYPESTACK_IS_RETURNADDRESS(a)) {
361 #ifdef TYPECHECK_DEBUG
362 if (!TYPESTACK_IS_RETURNADDRESS(b))
363 panic("Internal error: typestack_separable_from: unmergable stacks");
365 seta = TYPESTACK_RETURNADDRESSSET(a);
366 setb = TYPESTACK_RETURNADDRESSSET(b);
367 RETURNADDRESSSET_SEEK(setb,kb);
369 for (;seta;seta=seta->alt)
370 if (seta->addr != setb->addr) return true;
373 #ifdef TYPECHECK_DEBUG
374 if (b) panic("Internal error: typestack_separable_from: different depth");
379 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
381 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
383 typeinfo_retaddr_set *seta;
384 typeinfo_retaddr_set *setb;
386 for (; a; a = a->prev, b = b->prev) {
387 #ifdef TYPECHECK_DEBUG
388 if (!b) panic("Internal error: typestack_separable_from: different depth");
390 if (TYPESTACK_IS_RETURNADDRESS(a)) {
391 #ifdef TYPECHECK_DEBUG
392 if (!TYPESTACK_IS_RETURNADDRESS(b))
393 panic("Internal error: typestack_separable_from: unmergable stacks");
395 seta = TYPESTACK_RETURNADDRESSSET(a);
396 setb = TYPESTACK_RETURNADDRESSSET(b);
397 RETURNADDRESSSET_SEEK(seta,ka);
398 RETURNADDRESSSET_SEEK(setb,kb);
400 if (seta->addr != setb->addr) return true;
403 #ifdef TYPECHECK_DEBUG
404 if (b) panic("Internal error: typestack_separable_from: different depth");
409 /****************************************************************************/
410 /* TYPESTATE FUNCTIONS */
411 /****************************************************************************/
414 typestate_merge(stackptr deststack,typevector *destloc,
415 stackptr ystack,typevector *yloc,
416 int locsize,bool jsrencountered)
418 typevector *dvec,*yvec;
420 bool changed = false;
423 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
424 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
425 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
426 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,locsize)); LOGNL;
429 /* The stack is always merged. If there are returnAddresses on
430 * the stack they are ignored in this step. */
432 changed |= typestack_merge(deststack,ystack);
435 return typevector_merge(destloc,yloc,locsize);
437 for (yvec=yloc; yvec; yvec=yvec->alt) {
440 /* Check if the typestates (deststack,destloc) will be
441 * separable when (ystack,yvec) is added. */
443 if (!typestack_separable_with(deststack,ystack,ky)
444 && !typevectorset_separable_with(destloc,yvec,locsize))
446 /* No, the resulting set won't be separable, thus we
447 * may merge all states in (deststack,destloc) and
450 typestack_collapse(deststack);
451 typevectorset_collapse(destloc,locsize);
452 typevector_merge(destloc,yvec,locsize);
455 /* Yes, the resulting set will be separable. Thus we check
456 * if we may merge (ystack,yvec) with a single state in
457 * (deststack,destloc). */
459 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
460 if (!typestack_separable_from(ystack,ky,deststack,kd)
461 && !typevector_separable_from(yvec,dvec,locsize))
463 /* The typestate (ystack,yvec) is not separable from
464 * (deststack,dvec) by any returnAddress. Thus we may
465 * merge the states. */
467 changed |= typevector_merge(dvec,yvec,locsize);
473 /* The typestate (ystack,yvec) is separable from all typestates
474 * (deststack,destloc). Thus we must add this state to the
477 typestack_add(deststack,ystack,ky);
478 typevectorset_add(destloc,yvec,locsize);
487 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
488 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,locsize)); LOGNL;
498 typestate_reach(void *localbuf,
500 basicblock *destblock,
501 stackptr ystack,typevector *yloc,
502 int locsize,bool jsrencountered)
506 bool changed = false;
508 LOG1("reaching block L%03d",destblock->debug_nr);
509 TYPECHECK_COUNT(stat_reached);
511 destidx = destblock - block;
512 destloc = MGET_TYPEVECTOR(localbuf,destidx,locsize);
514 /* When branching backwards we have to check for uninitialized objects */
516 if (destblock <= current) {
520 TYPECHECK_COUNT(stat_backwards);
522 for (sp = ystack; sp; sp=sp->prev)
523 if (sp->type == TYPE_ADR &&
524 TYPEINFO_IS_NEWOBJECT(sp->typeinfo))
525 panic("Branching backwards with uninitialized object on stack");
527 for (i=0; i<locsize; ++i)
528 if (yloc->td[i].type == TYPE_ADR &&
529 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info))
530 panic("Branching backwards with uninitialized object in local variable");
533 if (destblock->flags == BBTYPECHECK_UNDEF) {
534 /* The destblock has never been reached before */
536 TYPECHECK_COUNT(stat_copied);
537 LOG1("block (index %04d) reached first time",destidx);
539 typestack_copy(destblock->instack,ystack,yloc);
540 COPY_TYPEVECTORSET(yloc,destloc,locsize);
544 /* The destblock has already been reached before */
546 TYPECHECK_COUNT(stat_merged);
547 LOG1("block (index %04d) reached before",destidx);
549 changed = typestate_merge(destblock->instack,destloc,
552 TYPECHECK_COUNTIF(changed,stat_merging_changed);
557 destblock->flags = BBTYPECHECK_REACHED;
558 if (destblock <= current) {LOG("REPEAT!"); return true;}
564 * see typestate_reach
567 typestate_ret(void *localbuf,
569 stackptr ystack,typevector *yloc,
570 int retindex,int locsize)
573 typevector *selected;
574 basicblock *destblock;
577 for (yvec=yloc; yvec; ) {
578 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex]))
579 panic("Illegal instruction: RET on non-returnAddress");
581 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
583 selected = typevectorset_select(&yvec,retindex,destblock);
585 repeat |= typestate_reach(localbuf,current,destblock,
586 ystack,selected,locsize,true);
591 /****************************************************************************/
592 /* HELPER FUNCTIONS */
593 /****************************************************************************/
595 /* If a field is checked, definingclass == implementingclass */
597 is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, classinfo *methodclass,
600 /* check access rights */
601 if (methodclass != definingclass) {
602 switch (flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) {
606 /* In the cases below, definingclass cannot be an interface */
609 if (definingclass->packagename != methodclass->packagename)
613 if (definingclass->packagename != methodclass->packagename) {
614 if (!builtin_isanysubclass(methodclass,implementingclass))
617 /* For protected access of super class members in another
618 * package the instance must be a subclass of or the same
619 * as the current class. */
620 LOG("protected access into other package");
621 implementingclass = methodclass;
625 if (definingclass != methodclass) {
626 LOG("private access");
631 panic("Invalid access flags");
636 if ((flags & ACC_STATIC) != 0) {
637 LOG("accessing STATIC member with instance");
641 if (implementingclass
642 && !TYPEINFO_IS_NULLTYPE(*instance)
643 && !TYPEINFO_IS_NEWOBJECT(*instance))
645 if (!typeinfo_is_assignable_to_classinfo(instance,
648 LOG("instance not assignable");
650 LOGSTRu(implementingclass->name); LOGNL; LOGFLUSH;
656 if ((flags & ACC_STATIC) == 0) {
657 LOG("accessing non-STATIC member without instance");
665 /****************************************************************************/
666 /* MACROS FOR LOCAL VARIABLE CHECKING */
667 /****************************************************************************/
669 #define INDEX_ONEWORD(num) \
670 do { if((num)<0 || (num)>=validlocals) \
671 panic("Invalid local variable index"); } while (0)
672 #define INDEX_TWOWORD(num) \
673 do { if((num)<0 || ((num)+1)>=validlocals) \
674 panic("Invalid local variable index"); } while (0)
676 #define STORE_ONEWORD(num,type) \
677 do {typevectorset_store(localset,num,type,NULL);} while(0)
679 #define STORE_TWOWORD(num,type) \
680 do {typevectorset_store_twoword(localset,num,type);} while(0)
682 #define CHECK_ONEWORD(num,tp) \
683 do {TYPECHECK_COUNT(stat_ins_primload); \
684 if (jsrencountered) { \
685 if (!typevectorset_checktype(localset,num,tp)) \
686 panic("Variable type mismatch"); \
689 if (localset->td[num].type != tp) \
690 panic("Variable type mismatch"); \
694 #define CHECK_TWOWORD(num,type) \
695 do {TYPECHECK_COUNT(stat_ins_primload); \
696 if (!typevectorset_checktype(localset,num,type)) \
697 panic("Variable type mismatch"); \
700 /****************************************************************************/
701 /* MACROS FOR STACK TYPE CHECKING */
702 /****************************************************************************/
704 /* These macros are for basic typechecks which were not done in stack.c */
706 #define TYPECHECK_STACK(sp,tp) \
707 do { if ((sp)->type != (tp)) \
708 panic("Wrong data type on stack"); } while(0)
710 #define TYPECHECK_ADR(sp) TYPECHECK_STACK(sp,TYPE_ADR)
711 #define TYPECHECK_INT(sp) TYPECHECK_STACK(sp,TYPE_INT)
712 #define TYPECHECK_LNG(sp) TYPECHECK_STACK(sp,TYPE_LNG)
713 #define TYPECHECK_FLT(sp) TYPECHECK_STACK(sp,TYPE_FLT)
714 #define TYPECHECK_DBL(sp) TYPECHECK_STACK(sp,TYPE_DBL)
716 #define TYPECHECK_ARGS1(t1) \
717 do {TYPECHECK_STACK(curstack,t1);} while (0)
718 #define TYPECHECK_ARGS2(t1,t2) \
719 do {TYPECHECK_ARGS1(t1); \
720 TYPECHECK_STACK(curstack->prev,t2);} while (0)
721 #define TYPECHECK_ARGS3(t1,t2,t3) \
722 do {TYPECHECK_ARGS2(t1,t2); \
723 TYPECHECK_STACK(curstack->prev->prev,t3);} while (0)
725 /****************************************************************************/
727 /****************************************************************************/
729 #define COPYTYPE(source,dest) \
730 {if ((source)->type == TYPE_ADR) \
731 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
733 #define ISBUILTIN(v) (iptr->val.a == (functionptr)(v))
735 /* TYPECHECK_REACH: executed, when the target block (tbptr) can be reached
736 * from the current block (bptr). The types of local variables and
737 * stack slots are propagated to the target block.
739 * bptr.......current block
740 * tbptr......target block
741 * dst........current output stack pointer
742 * numlocals..number of local variables
743 * localset...current local variable vectorset
744 * localbuf...local variable vectorset buffer
745 * jsrencountered...true if a JSR has been seen
747 * repeat.....changed to true if a block before the current
750 #define TYPECHECK_REACH \
752 repeat |= typestate_reach(localbuf,bptr,tbptr,dst, \
753 localset,numlocals,jsrencountered); \
757 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
759 * class........class of the current method
760 * numlocals....number of local variables
761 * localset.....current local variable vectorset
762 * initmethod...true if this is an <init> method
764 #define TYPECHECK_LEAVE \
766 if (initmethod && class != class_java_lang_Object) { \
767 /* check the marker variable */ \
768 LOG("Checking <init> marker"); \
769 if (!typevectorset_checktype(localset,numlocals-1,TYPE_INT))\
770 panic("<init> method does not initialize 'this'"); \
774 /****************************************************************************/
776 /****************************************************************************/
778 #define MAXPARAMS 255
780 /* typecheck is called directly after analyse_stack */
784 int b_count, b_index;
785 stackptr curstack; /* input stack top for current instruction */
786 stackptr srcstack; /* source stack for copying and merging */
787 int opcode; /* current opcode */
788 int i; /* temporary counter */
789 int len; /* for counting instructions, etc. */
790 bool superblockend; /* true if no fallthrough to next block */
791 bool repeat; /* if true, blocks are iterated over again */
792 instruction *iptr; /* pointer to current instruction */
793 basicblock *bptr; /* pointer to current basic block */
794 basicblock *tbptr; /* temporary for target block */
796 int numlocals; /* number of local variables */
797 int validlocals; /* number of valid local variable indices */
798 void *localbuf; /* local variable types for each block start */
799 typevector *localset; /* typevector set for local variables */
800 typevector *lset; /* temporary pointer */
801 typedescriptor *td; /* temporary pointer */
803 stackptr savedstackbuf = NULL; /* buffer for saving the stack */
804 stackptr savedstack = NULL; /* saved instack of current block */
806 stackelement excstack; /* instack for exception handlers */
808 typedescriptor returntype; /* return type of current method */
809 u1 *ptype; /* parameter types of called method */
810 typeinfo *pinfo; /* parameter typeinfos of called method */
811 int rtype; /* return type of called method */
812 typeinfo rinfo; /* typeinfo for return type of called method */
814 stackptr dst; /* output stack of current instruction */
815 basicblock **tptr; /* pointer into target list of switch instr. */
816 xtable **handlers; /* active exception handlers */
817 classinfo *cls; /* temporary */
818 bool maythrow; /* true if this instruction may throw */
819 static utf *name_init; /* "<init>" */
820 bool initmethod; /* true if this is an "<init>" method */
821 builtin_descriptor *builtindesc; /* temp. descriptor of builtin */
822 bool jsrencountered = false; /* true if we there was a JSR */
826 if (compileverbose) {
827 char logtext[MAXLOGTEXT];
828 sprintf(logtext, "Typechecking: ");
829 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
830 sprintf(logtext + strlen(logtext), ".");
831 utf_sprint(logtext + strlen(logtext), method->name);
832 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
836 #ifdef TYPECHECK_STATISTICS
837 int count_iterations = 0;
838 TYPECHECK_COUNT(stat_typechecked);
839 TYPECHECK_COUNT_FREQ(stat_locals,maxlocals,STAT_LOCALS);
840 TYPECHECK_COUNT_FREQ(stat_blocks,block_count/10,STAT_BLOCKS);
843 LOGSTR("\n==============================================================================\n");
844 DOLOG(show_icmd_method());
845 LOGSTR("\n==============================================================================\n");
846 LOGimpSTR("Entering typecheck: ");
847 LOGimpSTRu(method->name);
849 LOGimpSTRu(method->descriptor);
850 LOGimpSTR(" (class ");
851 LOGimpSTRu(method->class->name);
856 name_init = utf_new_char("<init>");
857 initmethod = (method->name == name_init);
859 /* Allocate buffer for method arguments */
861 ptype = DMNEW(u1,MAXPARAMS);
862 pinfo = DMNEW(typeinfo,MAXPARAMS);
864 LOG("Buffer allocated.\n");
866 /* reset all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
867 b_count = block_count;
869 while (--b_count >= 0) {
870 #ifdef TYPECHECK_DEBUG
871 if (bptr->flags != BBFINISHED && bptr->flags != BBDELETED
872 && bptr->flags != BBUNDEF)
875 LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
876 panic("Internal error: Unexpected block flags in typecheck()");
879 if (bptr->flags >= BBFINISHED) {
880 bptr->flags = BBTYPECHECK_UNDEF;
885 /* The first block is always reached */
886 if (block_count && block[0].flags == BBTYPECHECK_UNDEF)
887 block[0].flags = BBTYPECHECK_REACHED;
889 LOG("Blocks reset.\n");
891 /* number of local variables */
893 /* In <init> methods we use an extra local variable to signal if
894 * the 'this' reference has been initialized. */
895 numlocals = maxlocals;
896 validlocals = numlocals;
897 if (initmethod) numlocals++;
899 /* allocate the buffers for local variables */
900 localbuf = DMNEW_TYPEVECTOR(block_count+1, numlocals);
901 localset = MGET_TYPEVECTOR(localbuf,block_count,numlocals);
903 LOG("Variable buffer allocated.\n");
905 /* allocate the buffer of active exception handlers */
906 handlers = DMNEW(xtable*,method->exceptiontablelength + 1);
908 /* initialize the variable types of the first block */
909 /* to the types of the arguments */
910 lset = MGET_TYPEVECTOR(localbuf,0,numlocals);
916 /* if this is an instance method initialize the "this" ref type */
917 if (!(method->flags & ACC_STATIC)) {
919 panic("Not enough local variables for method arguments");
920 td->type = TYPE_ADDRESS;
922 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
924 TYPEINFO_INIT_CLASSINFO(td->info,class);
929 LOG("'this' argument set.\n");
931 /* the rest of the arguments and the return type */
932 i = typedescriptors_init_from_method_args(td,method->descriptor,
934 true, /* two word types use two slots */
937 i = numlocals - (td - lset->td);
939 td->type = TYPE_VOID;
943 LOG("Arguments set.\n");
945 /* initialize the input stack of exception handlers */
946 excstack.prev = NULL;
947 excstack.type = TYPE_ADR;
948 TYPEINFO_INIT_CLASSINFO(excstack.typeinfo,
949 class_java_lang_Throwable); /* changed later */
951 LOG("Exception handler stacks set.\n");
953 /* loop while there are still blocks to be checked */
955 TYPECHECK_COUNT(count_iterations);
959 b_count = block_count;
962 while (--b_count >= 0) {
963 LOGSTR1("---- BLOCK %04d, ",bptr-block);
964 LOGSTR1("blockflags: %d\n",bptr->flags);
967 if (bptr->flags == BBTYPECHECK_REACHED) {
968 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",bptr-block);
971 superblockend = false;
972 bptr->flags = BBFINISHED;
973 b_index = bptr - block;
975 /* init stack at the start of this block */
976 curstack = bptr->instack;
978 /* determine the active exception handlers for this block */
979 /* XXX could use a faster algorithm with sorted lists or
982 for (i=0; i<method->exceptiontablelength; ++i) {
983 if ((extable[i].start <= bptr) && (extable[i].end > bptr)) {
984 LOG1("active handler L%03d",extable[i].handler->debug_nr);
985 handlers[len++] = extable + i;
988 handlers[len] = NULL;
990 /* init variable types at the start of this block */
991 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(localbuf,b_index,numlocals),
994 for (i=0; i<numlocals; ++i)
995 if (localset->td[i].type == TYPE_ADR
996 && TYPEINFO_IS_NEWOBJECT(localset->td[i].info))
997 panic("Uninitialized object in local variable inside try block");
999 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
1002 /* loop over the instructions */
1004 iptr = bptr->iinstr;
1005 while (--len >= 0) {
1006 TYPECHECK_COUNT(stat_ins);
1007 DOLOG(show_icmd(iptr,false)); LOGNL; LOGFLUSH;
1010 myclass = iptr->clazz;
1016 /****************************************/
1017 /* STACK MANIPULATIONS */
1019 /* We just need to copy the typeinfo */
1020 /* for slots containing addresses. */
1022 /* XXX We assume that the destination stack
1023 * slots were continuously allocated in
1024 * memory. (The current implementation in
1029 COPYTYPE(curstack,dst);
1033 COPYTYPE(curstack,dst);
1034 COPYTYPE(curstack,dst-2);
1035 COPYTYPE(curstack->prev,dst-1);
1039 COPYTYPE(curstack,dst);
1040 COPYTYPE(curstack,dst-3);
1041 COPYTYPE(curstack->prev,dst-1);
1042 COPYTYPE(curstack->prev->prev,dst-2);
1046 COPYTYPE(curstack,dst);
1047 COPYTYPE(curstack->prev,dst-1);
1051 COPYTYPE(curstack,dst);
1052 COPYTYPE(curstack->prev,dst-1);
1053 COPYTYPE(curstack,dst-3);
1054 COPYTYPE(curstack->prev,dst-4);
1055 COPYTYPE(curstack->prev->prev,dst-2);
1059 COPYTYPE(curstack,dst);
1060 COPYTYPE(curstack->prev,dst-1);
1061 COPYTYPE(curstack,dst-4);
1062 COPYTYPE(curstack->prev,dst-5);
1063 COPYTYPE(curstack->prev->prev,dst-2);
1064 COPYTYPE(curstack->prev->prev->prev,dst-3);
1068 COPYTYPE(curstack,dst-1);
1069 COPYTYPE(curstack->prev,dst);
1072 /****************************************/
1082 /* PRIMITIVE VARIABLE ACCESS */
1084 case ICMD_ILOAD: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1085 case ICMD_FLOAD: CHECK_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1086 case ICMD_IINC: CHECK_ONEWORD(iptr->op1,TYPE_INT); break;
1087 case ICMD_LLOAD: CHECK_TWOWORD(iptr->op1,TYPE_LONG); break;
1088 case ICMD_DLOAD: CHECK_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1090 case ICMD_FSTORE: STORE_ONEWORD(iptr->op1,TYPE_FLOAT); break;
1091 case ICMD_ISTORE: STORE_ONEWORD(iptr->op1,TYPE_INT); break;
1092 case ICMD_LSTORE: STORE_TWOWORD(iptr->op1,TYPE_LONG); break;
1093 case ICMD_DSTORE: STORE_TWOWORD(iptr->op1,TYPE_DOUBLE); break;
1095 /****************************************/
1096 /* LOADING ADDRESS FROM VARIABLE */
1099 TYPECHECK_COUNT(stat_ins_aload);
1101 /* loading a returnAddress is not allowed */
1102 if (jsrencountered) {
1103 if (!typevectorset_checkreference(localset,iptr->op1))
1104 panic("illegal instruction: ALOAD loading non-reference");
1106 typevectorset_copymergedtype(localset,iptr->op1,&(dst->typeinfo));
1109 if (!TYPEDESC_IS_REFERENCE(localset->td[iptr->op1]))
1110 panic("illegal instruction: ALOAD loading non-reference");
1111 TYPEINFO_COPY(localset->td[iptr->op1].info,dst->typeinfo);
1115 /****************************************/
1116 /* STORING ADDRESS TO VARIABLE */
1120 TYPEINFO_IS_NEWOBJECT(curstack->typeinfo))
1121 panic("Storing uninitialized object in local variable inside try block");
1123 if (TYPESTACK_IS_RETURNADDRESS(curstack))
1124 typevectorset_store_retaddr(localset,iptr->op1,&(curstack->typeinfo));
1126 typevectorset_store(localset,iptr->op1,TYPE_ADDRESS,
1127 &(curstack->typeinfo));
1130 /****************************************/
1131 /* LOADING ADDRESS FROM ARRAY */
1134 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->typeinfo))
1135 panic("illegal instruction: AALOAD on non-reference array");
1137 typeinfo_init_component(&curstack->prev->typeinfo,&dst->typeinfo);
1141 /****************************************/
1145 TYPECHECK_COUNT(stat_ins_field);
1146 if (!TYPEINFO_IS_REFERENCE(curstack->prev->typeinfo))
1147 panic("illegal instruction: PUTFIELD on non-reference");
1148 if (TYPEINFO_IS_ARRAY(curstack->prev->typeinfo))
1149 panic("illegal instruction: PUTFIELD on array");
1151 /* check if the value is assignable to the field */
1153 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1155 if (TYPEINFO_IS_NEWOBJECT(curstack->prev->typeinfo)) {
1157 && !TYPEINFO_NEWOBJECT_INSTRUCTION(curstack->prev->typeinfo))
1159 /* uninitialized "this" instance */
1160 if (fi->class != class || (fi->flags & ACC_STATIC) != 0)
1161 panic("Setting unaccessible field in uninitialized object");
1164 panic("PUTFIELD on uninitialized object");
1168 if (!is_accessible(fi->flags,fi->class,fi->class, myclass,
1169 &(curstack->prev->typeinfo)))
1170 panic("PUTFIELD: field is not accessible");
1173 if (curstack->type != fi->type)
1174 panic("PUTFIELD type mismatch");
1175 if (fi->type == TYPE_ADR) {
1176 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1177 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1179 panic("PUTFIELD reference type not assignable");
1185 case ICMD_PUTSTATIC:
1186 TYPECHECK_COUNT(stat_ins_field);
1187 /* check if the value is assignable to the field */
1189 fieldinfo *fi = (fieldinfo*) iptr[0].val.a;
1191 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL))
1192 panic("PUTSTATIC: field is not accessible");
1194 if (curstack->type != fi->type)
1195 panic("PUTSTATIC type mismatch");
1196 if (fi->type == TYPE_ADR) {
1197 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
1198 if (!typeinfo_is_assignable(&(curstack->typeinfo),
1200 panic("PUTSTATIC reference type not assignable");
1207 TYPECHECK_COUNT(stat_ins_field);
1208 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1209 panic("illegal instruction: GETFIELD on non-reference");
1210 if (TYPEINFO_IS_ARRAY(curstack->typeinfo))
1211 panic("illegal instruction: GETFIELD on array");
1214 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1216 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,
1217 &(curstack->typeinfo)))
1218 panic("GETFIELD: field is not accessible");
1220 if (dst->type == TYPE_ADR) {
1221 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1227 case ICMD_GETSTATIC:
1228 TYPECHECK_COUNT(stat_ins_field);
1230 fieldinfo *fi = (fieldinfo *)(iptr->val.a);
1232 if (!is_accessible(fi->flags,fi->class,fi->class,myclass,NULL)) {
1233 printf("---------\n");
1234 utf_display(fi->class->name);
1236 utf_display(myclass->name);
1240 panic("GETSTATIC: field is not accessible");
1243 if (dst->type == TYPE_ADR) {
1244 TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
1250 /****************************************/
1251 /* PRIMITIVE ARRAY ACCESS */
1253 case ICMD_ARRAYLENGTH:
1254 if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo)
1255 && curstack->typeinfo.typeclass != pseudo_class_Arraystub)
1256 panic("illegal instruction: ARRAYLENGTH on non-array");
1261 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1262 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1263 panic("Array type mismatch");
1267 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1268 panic("Array type mismatch");
1272 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1273 panic("Array type mismatch");
1277 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1278 panic("Array type mismatch");
1282 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_INT))
1283 panic("Array type mismatch");
1287 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1288 panic("Array type mismatch");
1292 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->typeinfo,ARRAYTYPE_LONG))
1293 panic("Array type mismatch");
1298 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1299 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1300 panic("Array type mismatch");
1304 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1305 panic("Array type mismatch");
1309 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1310 panic("Array type mismatch");
1314 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1315 panic("Array type mismatch");
1319 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1320 panic("Array type mismatch");
1324 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1325 panic("Array type mismatch");
1329 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1330 panic("Array type mismatch");
1334 /****************************************/
1335 /* ADDRESS CONSTANTS */
1338 if (iptr->val.a == NULL)
1339 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1341 /* string constants (or constant for builtin function) */
1342 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1345 /****************************************/
1346 /* CHECKCAST AND INSTANCEOF */
1348 case ICMD_CHECKCAST:
1349 TYPECHECK_ADR(curstack);
1350 /* returnAddress is not allowed */
1351 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1352 panic("Illegal instruction: CHECKCAST on non-reference");
1354 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,(classinfo *)iptr[0].val.a);
1358 case ICMD_INSTANCEOF:
1359 TYPECHECK_ADR(curstack);
1360 /* returnAddress is not allowed */
1361 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1362 panic("Illegal instruction: INSTANCEOF on non-reference");
1365 /****************************************/
1366 /* BRANCH INSTRUCTIONS */
1369 superblockend = true;
1372 case ICMD_IFNONNULL:
1379 case ICMD_IF_ICMPEQ:
1380 case ICMD_IF_ICMPNE:
1381 case ICMD_IF_ICMPLT:
1382 case ICMD_IF_ICMPGE:
1383 case ICMD_IF_ICMPGT:
1384 case ICMD_IF_ICMPLE:
1385 case ICMD_IF_ACMPEQ:
1386 case ICMD_IF_ACMPNE:
1393 case ICMD_IF_LCMPEQ:
1394 case ICMD_IF_LCMPNE:
1395 case ICMD_IF_LCMPLT:
1396 case ICMD_IF_LCMPGE:
1397 case ICMD_IF_LCMPGT:
1398 case ICMD_IF_LCMPLE:
1399 TYPECHECK_COUNT(stat_ins_branch);
1400 tbptr = (basicblock *) iptr->target;
1402 /* propagate stack and variables to the target block */
1406 /****************************************/
1409 case ICMD_TABLESWITCH:
1410 TYPECHECK_COUNT(stat_ins_switch);
1412 s4 *s4ptr = iptr->val.a;
1413 s4ptr++; /* skip default */
1414 i = *s4ptr++; /* low */
1415 i = *s4ptr++ - i + 2; /* +1 for default target */
1417 goto switch_instruction_tail;
1419 case ICMD_LOOKUPSWITCH:
1420 TYPECHECK_COUNT(stat_ins_switch);
1422 s4 *s4ptr = iptr->val.a;
1423 s4ptr++; /* skip default */
1424 i = *s4ptr++ + 1; /* count +1 for default */
1426 switch_instruction_tail:
1427 tptr = (basicblock **)iptr->target;
1431 LOG2("target %d is block %04d",(tptr-(basicblock **)iptr->target)-1,tbptr-block);
1435 superblockend = true;
1438 /****************************************/
1439 /* RETURNS AND THROW */
1442 if (!typeinfo_is_assignable_to_classinfo(
1443 &curstack->typeinfo,class_java_lang_Throwable))
1444 panic("illegal instruction: ATHROW on non-Throwable");
1445 superblockend = true;
1450 if (!TYPEINFO_IS_REFERENCE(curstack->typeinfo))
1451 panic("illegal instruction: ARETURN on non-reference");
1453 if (returntype.type != TYPE_ADDRESS
1454 || !typeinfo_is_assignable(&curstack->typeinfo,&(returntype.info)))
1455 panic("Return type mismatch");
1459 if (returntype.type != TYPE_INT) panic("Return type mismatch");
1463 if (returntype.type != TYPE_LONG) panic("Return type mismatch");
1467 if (returntype.type != TYPE_FLOAT) panic("Return type mismatch");
1471 if (returntype.type != TYPE_DOUBLE) panic("Return type mismatch");
1475 if (returntype.type != TYPE_VOID) panic("Return type mismatch");
1478 superblockend = true;
1482 /****************************************/
1483 /* SUBROUTINE INSTRUCTIONS */
1487 jsrencountered = true;
1489 /* This is a dirty hack. It is needed
1490 * because of the special handling of
1491 * ICMD_JSR in stack.c
1493 dst = (stackptr) iptr->val.a;
1495 tbptr = (basicblock *) iptr->target;
1496 if (bptr+1 == last_block)
1497 panic("Illegal instruction: JSR at end of bytecode");
1498 typestack_put_retaddr(dst,bptr+1,localset);
1499 repeat |= typestate_reach(localbuf,bptr,tbptr,dst,
1500 localset,numlocals,true);
1502 superblockend = true;
1506 /* check returnAddress variable */
1507 if (!typevectorset_checkretaddr(localset,iptr->op1))
1508 panic("illegal instruction: RET using non-returnAddress variable");
1510 repeat |= typestate_ret(localbuf,bptr,curstack,
1511 localset,iptr->op1,numlocals);
1513 superblockend = true;
1516 /****************************************/
1519 case ICMD_INVOKEVIRTUAL:
1520 case ICMD_INVOKESPECIAL:
1521 case ICMD_INVOKESTATIC:
1522 case ICMD_INVOKEINTERFACE:
1523 TYPECHECK_COUNT(stat_ins_invoke);
1525 methodinfo *mi = (methodinfo*) iptr->val.a;
1526 bool specialmethod = (mi->name->text[0] == '<');
1527 bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
1529 classinfo *initclass;
1531 if (specialmethod && !callinginit)
1532 panic("Invalid invocation of special method");
1534 if (opcode == ICMD_INVOKESPECIAL) {
1535 /* XXX for INVOKESPECIAL: check if the invokation is done at all */
1537 /* (If callinginit the class is checked later.) */
1539 if (!builtin_isanysubclass(class,mi->class))
1540 panic("Illegal instruction: INVOKESPECIAL calling non-superclass method");
1544 /* fetch parameter types and return type */
1546 if (opcode != ICMD_INVOKESTATIC) {
1547 ptype[0] = TYPE_ADR;
1548 TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
1551 typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
1555 /* check parameter types */
1556 srcstack = curstack;
1557 i = mi->paramcount; /* number of parameters including 'this'*/
1560 if (srcstack->type != ptype[i])
1561 panic("Parameter type mismatch in method invocation");
1562 if (srcstack->type == TYPE_ADR) {
1563 LOGINFO(&(srcstack->typeinfo));
1565 if (i==0 && callinginit)
1567 /* first argument to <init> method */
1568 if (!TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo))
1569 panic("Calling <init> on initialized object");
1571 /* get the address of the NEW instruction */
1572 LOGINFO(&(srcstack->typeinfo));
1573 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
1574 initclass = (ins) ? (classinfo*)ins[-1].val.a : method->class;
1575 LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
1578 /* (This is checked below.) */
1579 /* TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
1580 /* if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
1581 /* panic("Parameter reference type mismatch in <init> invocation"); */
1584 if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
1585 panic("Parameter reference type mismatch in method invocation");
1590 if (i) srcstack = srcstack->prev;
1593 /* XXX We should resolve the method and pass its
1594 * class as implementingclass to is_accessible. */
1595 if (!is_accessible(mi->flags,mi->class,NULL, myclass,
1596 (opcode == ICMD_INVOKESTATIC) ? NULL
1597 : &(srcstack->typeinfo)))
1598 panic("Invoking unaccessible method");
1600 LOG("checking return type");
1601 if (rtype != TYPE_VOID) {
1602 if (rtype != dst->type)
1603 panic("Return type mismatch in method invocation");
1604 TYPEINFO_COPY(rinfo,dst->typeinfo);
1608 LOG("replacing uninitialized object");
1609 /* replace uninitialized object type on stack */
1612 if (srcstack->type == TYPE_ADR
1613 && TYPEINFO_IS_NEWOBJECT(srcstack->typeinfo)
1614 && TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo) == ins)
1616 LOG("replacing uninitialized type on stack");
1618 /* If this stackslot is in the instack of
1619 * this basic block we must save the type(s)
1620 * we are going to replace.
1622 if (srcstack <= bptr->instack && !savedstack)
1626 LOG("saving input stack types");
1627 if (!savedstackbuf) {
1628 LOG("allocating savedstack buffer");
1629 savedstackbuf = DMNEW(stackelement,maxstack);
1630 savedstackbuf->prev = NULL;
1631 for (i=1; i<maxstack; ++i)
1632 savedstackbuf[i].prev = savedstackbuf+(i-1);
1634 sp = savedstack = bptr->instack;
1635 copy = bptr->instack = savedstackbuf + (bptr->indepth-1);
1636 TYPESTACK_COPY(sp,copy);
1639 TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
1641 srcstack = srcstack->prev;
1643 /* replace uninitialized object type in locals */
1644 typevectorset_init_object(localset,ins,initclass,numlocals);
1646 /* initializing the 'this' reference? */
1648 #ifdef TYPECHECK_DEBUG
1650 panic("Internal error: calling <init> on this in non-<init> method.");
1652 /* must be <init> of current class or direct superclass */
1653 if (mi->class != class && mi->class != class->super)
1654 panic("<init> calling <init> of the wrong class");
1656 /* set our marker variable to type int */
1657 LOG("setting <init> marker");
1658 typevectorset_store(localset,numlocals-1,TYPE_INT,NULL);
1661 /* initializing an instance created with NEW */
1662 /* XXX is this strictness ok? */
1663 if (mi->class != initclass)
1664 panic("Calling <init> method of the wrong class");
1671 case ICMD_MULTIANEWARRAY:
1674 arraydescriptor *desc;
1676 /* check the array lengths on the stack */
1678 if (i<1) panic("MULTIANEWARRAY with dimensions < 1");
1679 srcstack = curstack;
1682 panic("MULTIANEWARRAY missing array length");
1683 if (srcstack->type != TYPE_INT)
1684 panic("MULTIANEWARRAY using non-int as array length");
1685 srcstack = srcstack->prev;
1688 /* check array descriptor */
1689 arrayvftbl = (vftbl*) iptr[0].val.a;
1691 panic("MULTIANEWARRAY with unlinked class");
1692 if ((desc = arrayvftbl->arraydesc) == NULL)
1693 panic("MULTIANEWARRAY with non-array class");
1694 if (desc->dimension < iptr[0].op1)
1695 panic("MULTIANEWARRAY dimension to high");
1697 /* set the array type of the result */
1698 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,arrayvftbl->class);
1704 TYPECHECK_COUNT(stat_ins_builtin);
1705 if (ISBUILTIN(BUILTIN_aastore)) {
1706 TYPECHECK_ADR(curstack);
1707 TYPECHECK_INT(curstack->prev);
1708 TYPECHECK_ADR(curstack->prev->prev);
1709 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(curstack->prev->prev->typeinfo))
1710 panic("illegal instruction: AASTORE to non-reference array");
1713 /* XXX put these checks in a function */
1714 TYPECHECK_COUNT(stat_ins_builtin_gen);
1715 builtindesc = builtin_desc;
1716 while (builtindesc->opcode && builtindesc->builtin
1717 != (functionptr) iptr->val.a) builtindesc++;
1718 if (!builtindesc->opcode) {
1719 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1720 panic("Internal error: builtin not found in table");
1722 TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
1728 TYPECHECK_COUNT(stat_ins_builtin);
1729 if (ISBUILTIN(BUILTIN_newarray))
1732 TYPECHECK_INT(curstack->prev);
1733 if (iptr[-1].opc != ICMD_ACONST)
1734 panic("illegal instruction: builtin_newarray without classinfo");
1735 vft = (vftbl *)iptr[-1].val.a;
1737 panic("ANEWARRAY with unlinked class");
1738 if (!vft->arraydesc)
1739 panic("ANEWARRAY with non-array class");
1740 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1742 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1745 TYPECHECK_ADR(curstack->prev);
1746 if (iptr[-1].opc != ICMD_ACONST)
1747 panic("illegal instruction: builtin_arrayinstanceof without classinfo");
1748 vft = (vftbl *)iptr[-1].val.a;
1750 panic("INSTANCEOF with unlinked class");
1751 if (!vft->arraydesc)
1752 panic("internal error: builtin_arrayinstanceof with non-array class");
1754 else if (ISBUILTIN(BUILTIN_checkarraycast)) {
1756 TYPECHECK_ADR(curstack->prev);
1757 if (iptr[-1].opc != ICMD_ACONST)
1758 panic("illegal instruction: BUILTIN_checkarraycast without classinfo");
1759 vft = (vftbl *)iptr[-1].val.a;
1761 panic("CHECKCAST with unlinked class");
1762 if (!vft->arraydesc)
1763 panic("internal error: builtin_checkarraycast with non-array class");
1764 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1767 TYPECHECK_COUNT(stat_ins_builtin_gen);
1768 builtindesc = builtin_desc;
1769 while (builtindesc->opcode && builtindesc->builtin
1770 != (functionptr) iptr->val.a) builtindesc++;
1771 if (!builtindesc->opcode) {
1772 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1773 panic("Internal error: builtin not found in table");
1775 TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
1781 TYPECHECK_COUNT(stat_ins_builtin);
1782 if (ISBUILTIN(BUILTIN_new)) {
1784 if (iptr[-1].opc != ICMD_ACONST)
1785 panic("illegal instruction: builtin_new without classinfo");
1786 cls = (classinfo *) iptr[-1].val.a;
1788 panic("Internal error: NEW with unlinked class");
1789 /* The following check also forbids array classes and interfaces: */
1790 if ((cls->flags & ACC_ABSTRACT) != 0)
1791 panic("Invalid instruction: NEW creating instance of abstract class");
1792 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,iptr);
1794 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1795 TYPECHECK_INT(curstack);
1796 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1798 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1799 TYPECHECK_INT(curstack);
1800 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1802 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1803 TYPECHECK_INT(curstack);
1804 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1806 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1807 TYPECHECK_INT(curstack);
1808 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1810 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1811 TYPECHECK_INT(curstack);
1812 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1814 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1815 TYPECHECK_INT(curstack);
1816 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1818 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1819 TYPECHECK_INT(curstack);
1820 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1822 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1823 TYPECHECK_INT(curstack);
1824 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1827 TYPECHECK_COUNT(stat_ins_builtin_gen);
1828 builtindesc = builtin_desc;
1829 while (builtindesc->opcode && builtindesc->builtin
1830 != (functionptr) iptr->val.a) builtindesc++;
1831 if (!builtindesc->opcode) {
1832 dolog("Builtin not in table: %s",icmd_builtin_name((functionptr) iptr->val.a));
1833 panic("Internal error: builtin not found in table");
1835 TYPECHECK_ARGS1(builtindesc->type_s1);
1840 /****************************************/
1841 /* SIMPLE EXCEPTION THROWING TESTS */
1843 case ICMD_CHECKASIZE:
1844 /* The argument to CHECKASIZE is typechecked by
1845 * typechecking the array creation instructions. */
1848 case ICMD_NULLCHECKPOP:
1849 /* NULLCHECKPOP just requires that the stack top
1850 * is an address. This is checked in stack.c */
1855 /****************************************/
1856 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1857 /* REPLACED BY OTHER OPCODES */
1859 #ifdef TYPECHECK_DEBUG
1862 case ICMD_ANEWARRAY:
1863 case ICMD_MONITORENTER:
1864 case ICMD_MONITOREXIT:
1866 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1867 LOG("Should have been converted to builtin function call.");
1868 panic("Internal error: unexpected instruction encountered");
1871 case ICMD_READONLY_ARG:
1872 case ICMD_CLEAR_ARGREN:
1873 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1874 LOG("Should have been replaced in stack.c.");
1875 panic("Internal error: unexpected pseudo instruction encountered");
1879 /****************************************/
1880 /* UNCHECKED OPERATIONS */
1882 /*********************************************
1883 * Instructions below...
1884 * *) don't operate on local variables,
1885 * *) don't operate on references,
1886 * *) don't operate on returnAddresses.
1888 * (These instructions are typechecked in
1890 ********************************************/
1892 /* Instructions which may throw a runtime exception: */
1902 /* Instructions which never throw a runtime exception: */
1903 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
1913 case ICMD_IFEQ_ICONST:
1914 case ICMD_IFNE_ICONST:
1915 case ICMD_IFLT_ICONST:
1916 case ICMD_IFGE_ICONST:
1917 case ICMD_IFGT_ICONST:
1918 case ICMD_IFLE_ICONST:
1919 case ICMD_ELSE_ICONST:
1941 case ICMD_IREM0X10001:
1942 case ICMD_LREM0X10001:
1945 case ICMD_IADDCONST:
1946 case ICMD_ISUBCONST:
1947 case ICMD_IMULCONST:
1948 case ICMD_IANDCONST:
1950 case ICMD_IXORCONST:
1951 case ICMD_ISHLCONST:
1952 case ICMD_ISHRCONST:
1953 case ICMD_IUSHRCONST:
1955 case ICMD_LADDCONST:
1956 case ICMD_LSUBCONST:
1957 case ICMD_LMULCONST:
1958 case ICMD_LANDCONST:
1960 case ICMD_LXORCONST:
1961 case ICMD_LSHLCONST:
1962 case ICMD_LSHRCONST:
1963 case ICMD_LUSHRCONST:
1980 case ICMD_INT2SHORT:
1983 case ICMD_LCMPCONST:
2002 TYPECHECK_COUNT(stat_ins_unchecked);
2005 /****************************************/
2008 LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
2009 panic("Missing ICMD code during typecheck");
2013 /* the output of this instruction becomes the current stack */
2016 /* reach exception handlers for this instruction */
2018 LOG("reaching exception handlers");
2020 while (handlers[i]) {
2021 TYPECHECK_COUNT(stat_handlers_reached);
2022 cls = handlers[i]->catchtype;
2023 excstack.typeinfo.typeclass = (cls) ? cls
2024 : class_java_lang_Throwable;
2025 repeat |= typestate_reach(localbuf,bptr,
2026 handlers[i]->handler,
2035 } /* while instructions */
2037 LOG("instructions done");
2038 LOGSTR("RESULT=> ");
2039 DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
2042 /* propagate stack and variables to the following block */
2043 if (!superblockend) {
2044 LOG("reaching following block");
2046 while (tbptr->flags == BBDELETED) {
2048 #ifdef TYPECHECK_DEBUG
2049 if ((tbptr-block) >= block_count)
2050 panic("Control flow falls off the last block");
2056 /* We may have to restore the types of the instack slots. They
2057 * have been saved if an <init> call inside the block has
2058 * modified the instack types. (see INVOKESPECIAL) */
2061 stackptr sp = bptr->instack;
2062 stackptr copy = savedstack;
2063 TYPECHECK_COUNT(stat_savedstack);
2064 LOG("restoring saved instack");
2065 TYPESTACK_COPY(sp,copy);
2066 bptr->instack = savedstack;
2070 } /* if block has to be checked */
2072 } /* while blocks */
2074 LOGIF(repeat,"repeat=true");
2077 #ifdef TYPECHECK_STATISTICS
2078 dolog("Typechecker did %4d iterations",count_iterations);
2079 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2080 TYPECHECK_COUNTIF(jsrencountered,stat_typechecked_jsr);
2083 #ifdef TYPECHECK_DEBUG
2084 for (i=0; i<block_count; ++i) {
2085 if (block[i].flags != BBDELETED
2086 && block[i].flags != BBUNDEF
2087 && block[i].flags != BBFINISHED
2088 && block[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2089 * some exception handlers,
2092 LOG2("block L%03d has invalid flags after typecheck: %d",
2093 block[i].debug_nr,block[i].flags);
2094 panic("Invalid block flags after typecheck");
2099 /* Reset blocks we never reached */
2100 for (i=0; i<block_count; ++i) {
2101 if (block[i].flags == BBTYPECHECK_UNDEF)
2102 block[i].flags = BBFINISHED;
2105 LOGimp("exiting typecheck");
2107 if (compileverbose) {
2108 char logtext[MAXLOGTEXT];
2109 sprintf(logtext, "Typechecking done: ");
2110 utf_sprint_classname(logtext + strlen(logtext), method->class->name);
2111 sprintf(logtext + strlen(logtext), ".");
2112 utf_sprint(logtext + strlen(logtext), method->name);
2113 utf_sprint_classname(logtext + strlen(logtext), method->descriptor);
2120 #endif /* CACAO_TYPECHECK */
2123 * These are local overrides for various environment variables in Emacs.
2124 * Please do not remove this and leave it at the end of the file, where
2125 * Emacs will automagically detect them.
2126 * ---------------------------------------------------------------------
2129 * indent-tabs-mode: t