1 /* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "vm/builtin.h"
35 #include "mm/memory.h"
38 #include "vm/global.h"
39 #include "vm/primitive.h"
41 #include "vm/jit/parse.h"
42 #include "vm/jit/show.h"
43 #include "vm/jit/stack.h"
44 #include "vm/jit/verify/typecheck-common.h"
47 /* this #if runs over the whole file: */
48 #if defined(ENABLE_VERIFIER)
50 typedef typedescriptor verifier_slot_t;
52 #if defined(TYPECHECK_VERBOSE)
53 static void typecheck_stackbased_show_state(verifier_state *state,
54 typedescriptor *stack,
55 typedescriptor *stackfloor,
60 #define CHECK_STACK_DEPTH(d) \
61 if (((u1*)stack - (u1*)stackfloor) \
62 < (((d)-1) * (int)sizeof(verifier_slot_t))) \
63 goto throw_stack_underflow;
65 /* XXX don't need to check against ACONST for every ICMD */
66 #define CHECK_STACK_SPACE(d) \
67 if (((u1*)STATE->stackceiling - (u1*)stack) \
68 < (((d)+1) * (int)sizeof(verifier_slot_t))) \
69 if (STATE->iptr->opc != ICMD_ACONST \
70 || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
71 goto throw_stack_overflow;
73 #define CHECK_STACK_TYPE(s, t) \
74 if ((s).type != (t)) \
75 goto throw_stack_type_error;
78 #define CHECK_LOCAL_TYPE(index, t) \
80 if (state.locals[(index)].type != (t)) \
81 goto throw_local_type_error; \
83 STATE->topjsr->usedlocals[(index)] = 1; \
84 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
85 STATE->topjsr->usedlocals[(index) + 1] = 1; \
89 #define STORE_LOCAL(t, index) \
91 state.locals[(index)].type = (t); \
92 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
93 state.locals[(index-1)].type = TYPE_VOID; \
95 STATE->topjsr->usedlocals[(index)] = 1; \
99 #define STORE_LOCAL_2_WORD(t, index) \
101 STORE_LOCAL(t, index); \
102 state.locals[(index)+1].type = TYPE_VOID; \
104 STATE->topjsr->usedlocals[(index)] = 1; \
107 #define VERIFY_ERROR(msg) \
109 LOG1("VerifyError: %s", msg); \
110 exceptions_throw_verifyerror(STATE->m, msg); \
114 #define IS_CAT1(slot) \
115 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
117 #define IS_CAT2(slot) \
118 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
120 #define CHECK_CAT1(slot) \
122 if (!IS_CAT1(slot)) \
123 goto throw_stack_category_error; \
126 #define CHECK_CAT2(slot) \
128 if (!IS_CAT2(slot)) \
129 goto throw_stack_category_error; \
132 #define COPY_SLOT(s, d) \
133 do { (d) = (s); } while (0)
135 #define REACH_BLOCK(target) \
137 if (!typecheck_stackbased_reach(STATE, (target), stack, \
138 (stack - stackfloor) + 1)) \
142 #define REACH(target) \
144 REACH_BLOCK((target).block); \
153 /* XXX should reuse typevector code */
154 static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
159 bool changed = false;
162 typedescriptor *a = dst;
163 typedescriptor *b = y;
165 if (a->type != TYPE_VOID && a->type != b->type) {
169 else if (a->type == TYPE_ADR) {
170 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
171 /* 'a' is a returnAddress */
172 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
173 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
174 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
181 /* 'a' is a reference */
182 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
187 /* two reference types are merged. There cannot be */
188 /* a merge error. In the worst case we get j.l.O. */
189 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
190 if (r == typecheck_FAIL)
202 static typecheck_result typecheck_stackbased_merge(verifier_state *state,
203 basicblock *destblock,
204 typedescriptor *stack,
209 typedescriptor *stackfloor;
213 bool changed = false;
215 destidx = destblock->nr;
217 if (stackdepth != state->indepth[destidx]) {
218 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
219 return typecheck_FAIL;
222 stackfloor = stack - (stackdepth - 1);
225 dp = state->startstack + (destidx * state->m->maxstack);
227 for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
228 if (sp->type != dp->type) {
229 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
230 return typecheck_FAIL;
232 if (dp->type == TYPE_ADR) {
233 if (TYPEINFO_IS_PRIMITIVE(dp->typeinfo)) {
234 /* dp has returnAddress type */
235 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
236 if (TYPEINFO_RETURNADDRESS(dp->typeinfo) != TYPEINFO_RETURNADDRESS(sp->typeinfo)) {
237 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
238 return typecheck_FAIL;
242 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
243 return typecheck_FAIL;
247 /* dp has reference type */
248 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
249 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
250 return typecheck_FAIL;
252 r = typeinfo_merge(state->m,&(dp->typeinfo),&(sp->typeinfo));
253 if (r == typecheck_FAIL)
260 dp = state->startlocals + (destidx * state->numlocals);
261 r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
262 if (r == typecheck_FAIL)
269 static bool typecheck_stackbased_reach(verifier_state *state,
270 basicblock *destblock,
271 typedescriptor *stack,
274 bool changed = false;
279 if (destblock->flags == BBTYPECHECK_UNDEF) {
280 /* The destblock has never been reached before */
282 TYPECHECK_COUNT(stat_copied);
283 LOG1("block L%03d reached first time",destblock->nr); LOGSTR("\t");
284 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
286 state->indepth[destblock->nr] = stackdepth;
288 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
289 stack - (stackdepth - 1),
293 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
301 /* The destblock has already been reached before */
303 TYPECHECK_COUNT(stat_merged);
304 LOG1("block L%03d reached before", destblock->nr); LOGSTR("\t");
305 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
307 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
308 if (r == typecheck_FAIL)
312 TYPECHECK_COUNTIF(changed,stat_merging_changed);
317 destblock->flags = BBTYPECHECK_REACHED;
318 /* XXX is this check ok? */
319 if (destblock->nr <= state->bptr->nr) {
321 state->repeat = true;
328 /* typecheck_stackbased_verify_fieldaccess *************************************
330 Verify an ICMD_{GET,PUT}{STATIC,FIELD}
333 state............the current state of the verifier
334 instance.........the instance slot, or NULL
335 value............the value slot, or NULL
336 stack............stack after popping the arguments
339 stack pointer....successful verification,
340 NULL.............an exception has been thrown.
342 *******************************************************************************/
344 static typedescriptor *typecheck_stackbased_verify_fieldaccess(
345 verifier_state *state,
346 typedescriptor *instance,
347 typedescriptor *value,
348 typedescriptor *stack)
354 #define TYPECHECK_STACKBASED
355 #define EXCEPTION do { return NULL; } while (0)
357 #include <typecheck-fields.inc>
360 #undef TYPECHECK_STACKBASED
364 throw_stack_overflow:
365 LOG("STACK OVERFLOW!");
366 exceptions_throw_verifyerror(state->m, "Stack size too large");
370 static bool typecheck_stackbased_verify_invocation(verifier_state *state,
371 typedescriptor *stack,
372 typedescriptor *stackfloor)
378 /* check stack depth */
380 /* XXX parse params */
382 INSTRUCTION_GET_METHODDESC(state->iptr, md);
384 paramslots = md->paramslots;
386 if ((stack - stackfloor) + 1 < paramslots) {
387 exceptions_throw_verifyerror(state->m,
388 "Trying to pop operand of an empty stack");
392 dv = stack - (paramslots - 1);
394 #define TYPECHECK_STACKBASED
396 #include <typecheck-invoke.inc>
398 #undef TYPECHECK_STACKBASED
403 static bool typecheck_stackbased_verify_builtin(verifier_state *state,
404 typedescriptor *stack,
405 typedescriptor *stackfloor)
410 /* check stack depth */
412 /* XXX parse params */
414 paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
416 if ((stack - stackfloor) + 1 < paramslots) {
417 exceptions_throw_verifyerror(state->m,
418 "Trying to pop operand of an empty stack");
422 dv = stack - (paramslots - 1);
424 #define TYPECHECK_STACKBASED
426 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
427 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
428 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
429 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
430 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
431 #include <typecheck-builtins.inc>
433 #undef TYPECHECK_STACKBASED
437 throw_stack_type_error:
438 exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
442 static bool typecheck_stackbased_multianewarray(verifier_state *state,
443 typedescriptor *stack,
444 typedescriptor *stackfloor)
446 /* XXX recombine with verify_multianewarray */
448 classinfo *arrayclass;
449 arraydescriptor *desc;
454 /* destination slot */
456 i = state->iptr->s1.argcount;
460 /* check the array lengths on the stack */
462 if ((stack - stackfloor) + 1 < i) {
463 exceptions_throw_verifyerror(state->m,
464 "Trying to pop operand of an empty stack");
469 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
471 for (sp = dst; sp <= stack; ++sp) {
472 if (sp->type != TYPE_INT) {
473 exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
478 /* check array descriptor */
480 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
481 /* the array class reference has already been resolved */
482 arrayclass = state->iptr->sx.s23.s3.c.cls;
484 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
485 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
486 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
487 if (desc->dimension < state->iptr->s1.argcount)
488 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
490 /* set the array type of the result */
491 typeinfo_init_classinfo(&(dst->typeinfo), arrayclass);
495 constant_classref *cr;
497 /* the array class reference is still unresolved */
498 /* check that the reference indicates an array class of correct dimension */
499 cr = state->iptr->sx.s23.s3.c.ref;
504 /* { the dimension of the array class == i } */
506 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
507 if (i < state->iptr->s1.argcount)
508 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
510 /* set the array type of the result */
511 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
520 static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
523 typecheck_jsr_caller_t *jc;
525 for (jc = jsr->callers; jc; jc = jc->next)
526 if (jc->callblock == bptr)
529 jc = DNEW(typecheck_jsr_caller_t);
530 jc->next = jsr->callers;
531 jc->callblock = bptr;
535 static typedescriptor *typecheck_stackbased_jsr(verifier_state *state,
536 typedescriptor *stack,
537 typedescriptor *stackfloor)
539 typecheck_jsr_t *jsr;
546 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
547 jsr = state->jsrinfos[tbptr->nr];
549 if (jsr && tbptr->flags == BBFINISHED) {
551 LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
553 exceptions_throw_verifyerror(state->m, "Recursive JSR");
557 assert(jsr->callers);
558 assert(jsr->callers->callblock);
560 /* copy the stack of the RET edge */
562 MCOPY(stackfloor, jsr->retstack, typedescriptor, jsr->retdepth);
563 stack = stackfloor + (jsr->retdepth - 1);
565 /* copy variables that were used in the subroutine from the RET edge */
567 for (i=0; i<state->numlocals; ++i)
568 if (jsr->usedlocals[i])
569 state->locals[i] = jsr->retlocals[i];
571 /* reach the following block */
573 if (!typecheck_stackbased_reach(state, state->bptr->next, stack,
574 (stack - stackfloor) + 1))
579 LOG1("first JSR to block L%03d", tbptr->nr);
581 jsr = DNEW(typecheck_jsr_t);
582 state->jsrinfos[tbptr->nr] = jsr;
584 jsr->blockflags = DMNEW(char, state->basicblockcount);
585 jsr->retblock = NULL;
587 jsr->usedlocals = DMNEW(char, state->numlocals);
588 MZERO(jsr->usedlocals, char, state->numlocals);
589 jsr->retlocals = DMNEW(typedescriptor, state->numlocals);
590 jsr->retstack = DMNEW(typedescriptor, state->m->maxstack);
594 LOG1("re-analysing JSR to block L%03d", tbptr->nr);
598 jsr->next = state->topjsr;
601 assert(state->iptr->sx.s23.s3.jsrtarget.block->flags == BBTYPECHECK_REACHED);
603 tbptr->flags = BBFINISHED;
605 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
606 jsr->blockflags[tbptr->nr] = tbptr->flags;
608 if (tbptr->flags == BBTYPECHECK_REACHED)
609 tbptr->flags = BBFINISHED;
612 state->iptr->sx.s23.s3.jsrtarget.block->flags = BBTYPECHECK_REACHED;
615 /* register this block as a caller, if not already done */
617 typecheck_stackbased_add_jsr_caller(jsr, state->bptr);
622 static bool typecheck_stackbased_ret(verifier_state *state,
623 typedescriptor *stack,
624 typedescriptor *stackfloor)
627 typecheck_jsr_caller_t *jsrcaller;
628 typecheck_jsr_t *jsr;
631 /* get the subroutine we are RETurning from */
633 tbptr = TYPEINFO_RETURNADDRESS(state->locals[state->iptr->s1.varindex].typeinfo);
635 exceptions_throw_verifyerror(state->m, "Illegal RET");
639 LOG1("RET from subroutine L%03d", tbptr->nr);
640 jsr = state->jsrinfos[tbptr->nr];
643 /* check against recursion */
646 exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
650 /* check against multiple RETs for one subroutine */
652 if (jsr->retblock && jsr->retblock != state->bptr) {
653 exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
657 /* store data-flow of the RET edge */
659 jsr->retblock = state->bptr;
660 jsr->retdepth = (stack - stackfloor) + 1;
661 MCOPY(jsr->retstack, stackfloor, typedescriptor, jsr->retdepth);
662 MCOPY(jsr->retlocals, state->locals, typedescriptor, state->numlocals);
664 /* invalidate the returnAddress used by this RET */
665 /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
667 for (i=0; i<state->numlocals; ++i) {
668 typedescriptor *lc = &(jsr->retlocals[i]);
669 if (TYPE_IS_RETURNADDRESS(lc->type, lc->typeinfo))
670 if (TYPEINFO_RETURNADDRESS(lc->typeinfo) == tbptr) {
671 LOG1("invalidating returnAddress in local %d", i);
672 TYPEINFO_INIT_RETURNADDRESS(lc->typeinfo, NULL);
676 /* touch all callers of the subroutine, so they are analysed again */
678 for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
679 tbptr = jsrcaller->callblock;
680 LOG1("touching caller L%03d from RET", tbptr->nr);
681 assert(jsr->blockflags[tbptr->nr] >= BBFINISHED);
682 jsr->blockflags[tbptr->nr] = BBTYPECHECK_REACHED; /* XXX repeat? */
688 bool typecheck_stackbased(jitdata *jd)
690 register verifier_slot_t *stack;
691 verifier_slot_t *stackfloor;
696 verifier_slot_t temp;
697 branch_target_t *table;
698 lookup_target_t *lookup;
701 verifier_slot_t *dst;
702 verifier_state state;
705 typedescriptor exstack;
708 DOLOG( show_method(jd, SHOW_PARSE); );
710 /* initialize verifier state */
715 state.basicblocks = jd->basicblocks;
716 state.basicblockcount = jd->basicblockcount;
718 # define STATE (&state)
720 /* check that the basicblock numbers are valid */
723 jit_check_basicblock_numbers(jd);
726 /* check if this method is an instance initializer method */
728 state.initmethod = (state.m->name == utf_init);
730 /* allocate parameter descriptors if necessary */
732 if (!state.m->parseddesc->params)
733 if (!descriptor_params_from_paramtypes(state.m->parseddesc,state.m->flags))
736 /* allocate the stack buffers */
738 stackfloor = DMNEW(verifier_slot_t, state.m->maxstack + 1);
739 state.stackceiling = stackfloor + state.m->maxstack;
740 stack = stackfloor - 1;
741 state.indepth = DMNEW(s4, state.basicblockcount);
742 state.startstack = DMNEW(verifier_slot_t, state.m->maxstack * state.basicblockcount);
744 /* allocate the local variables buffers */
746 state.numlocals = state.m->maxlocals;
747 state.validlocals = state.m->maxlocals;
748 if (state.initmethod)
749 state.numlocals++; /* extra marker variable */
751 state.locals = DMNEW(verifier_slot_t, state.numlocals);
752 state.startlocals = DMNEW(verifier_slot_t, state.numlocals * state.basicblockcount);
754 /* allocate the buffer of active exception handlers */
756 state.handlers = DMNEW(exception_entry*, state.jd->exceptiontablelength + 1);
758 /* initialize instack of exception handlers */
760 exstack.type = TYPE_ADR;
761 typeinfo_init_classinfo(&(exstack.typeinfo),
762 class_java_lang_Throwable); /* changed later */
764 LOG("Exception handler stacks set.\n");
766 /* initialize jsr info buffer */
768 state.jsrinfos = DMNEW(typecheck_jsr_t *, state.basicblockcount);
769 MZERO(state.jsrinfos, typecheck_jsr_t *, state.basicblockcount);
771 /* initialize stack of first block */
773 state.indepth[0] = 0;
775 /* initialize locals of first block */
777 /* if this is an instance method initialize the "this" ref type */
779 if (!(state.m->flags & ACC_STATIC)) {
780 if (state.validlocals < 1)
781 VERIFY_ERROR("Not enough local variables for method arguments");
782 dst = state.startlocals;
783 dst->type = TYPE_ADR;
784 if (state.initmethod)
785 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo, NULL);
787 typeinfo_init_classinfo(&(dst->typeinfo), state.m->class);
792 LOG("'this' argument set.\n");
794 len = typedescriptors_init_from_methoddesc(state.startlocals + skip,
796 state.validlocals, true, skip, &state.returntype);
800 /* set remaining locals to void */
802 for (i = skip + len; i<state.numlocals; ++i)
803 state.startlocals[i].type = TYPE_VOID;
805 /* initialize block flags */
807 typecheck_init_flags(&state, BBUNDEF);
809 /* iterate until fixpoint reached */
813 state.repeat = false;
815 /* iterate over the basic blocks */
817 for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
819 if (state.bptr->flags != BBTYPECHECK_REACHED)
822 DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
824 /* mark this block as analysed */
826 state.bptr->flags = BBFINISHED;
828 /* determine the active exception handlers for this block */
829 /* XXX could use a faster algorithm with sorted lists or */
831 /* XXX reuse code from variables based verifer? */
833 for (ex = STATE->jd->exceptiontable; ex ; ex = ex->down) {
834 if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
835 LOG1("\tactive handler L%03d", ex->handler->nr);
836 STATE->handlers[len++] = ex;
839 STATE->handlers[len] = NULL;
841 /* initialize the locals */
844 state.startlocals + (state.bptr->nr * state.numlocals),
845 verifier_slot_t, state.numlocals);
847 /* initialize the stack */
849 len = state.indepth[state.bptr->nr];
852 state.startstack + (state.bptr->nr * state.m->maxstack),
853 verifier_slot_t, len);
855 stack = stackfloor + (len - 1);
857 /* iterate over the instructions in this block */
859 state.iptr = state.bptr->iinstr;
860 len = state.bptr->icount;
862 superblockend = false;
864 for (; len--; state.iptr++) {
869 DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
871 switch (state.iptr->opc) {
872 #define TYPECHECK_STACKBASED 1
873 #define STATE (&state)
874 #define IPTR state.iptr
875 #define BPTR state.bptr
876 #define METHOD state.m
877 #define LOCAL_SLOT(index) (state.locals + (index))
880 LOG("EXCEPTION THROWN!\n"); \
884 #include <typecheck-stackbased-gen.inc>
885 #undef TYPECHECK_STACKBASED
888 /* reach exception handlers for this instruction */
891 TYPECHECK_COUNT(stat_ins_maythrow);
892 TYPECHECK_MARK(STATE->stat_maythrow);
893 LOG("\treaching exception handlers");
895 while (STATE->handlers[i]) {
896 TYPECHECK_COUNT(stat_handlers_reached);
897 if (STATE->handlers[i]->catchtype.any)
898 exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
900 exstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
901 if (!typecheck_stackbased_reach(
903 STATE->handlers[i]->handler,
911 /* propagate types to the following block */
913 if (!superblockend) {
914 if (!typecheck_stackbased_reach(&state, state.bptr->next,
915 stack, stack - stackfloor + 1))
918 } /* end loop over blocks */
920 while (!state.repeat && state.topjsr) {
921 LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
923 /* propagate down used locals */
925 if (state.topjsr->next) {
926 for (i=0; i<state.numlocals; ++i)
927 state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
930 /* restore REACHED flags */
932 for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
933 assert(tbptr->flags != BBTYPECHECK_REACHED);
934 if (state.topjsr->blockflags[tbptr->nr] == BBTYPECHECK_REACHED) {
935 tbptr->flags = BBTYPECHECK_REACHED;
940 /* dactivate the subroutine */
942 state.topjsr->active = false;
943 state.topjsr = state.topjsr->next;
945 } while (state.repeat);
947 /* reset block flags */
949 typecheck_reset_flags(&state);
951 LOG("typecheck_stackbased successful");
955 throw_stack_underflow:
956 LOG("STACK UNDERFLOW!");
957 exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
960 throw_stack_overflow:
961 LOG("STACK OVERFLOW!");
962 exceptions_throw_verifyerror(state.m, "Stack size too large");
965 throw_stack_type_error:
966 LOG("STACK TYPE ERROR!");
967 exceptions_throw_verifyerror(state.m, "Mismatched stack types");
970 throw_local_type_error:
971 LOG("LOCAL TYPE ERROR!");
972 exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
975 throw_stack_category_error:
976 LOG("STACK CATEGORY ERROR!");
977 exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
982 #if defined(TYPECHECK_VERBOSE)
983 static void typecheck_stackbased_show_state(verifier_state *state,
984 typedescriptor *stack,
985 typedescriptor *stackfloor,
991 LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
992 for (sp=stackfloor; sp <= stack; sp++) {
994 DOLOG( typedescriptor_print(stdout, sp); );
996 LOGSTR(" ] locals [");
997 for (i=0; i<state->numlocals; ++i) {
999 DOLOG( typedescriptor_print(stdout, state->locals + i); );
1003 if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
1005 DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
1011 #endif /* defined(ENABLE_VERIFIER) */
1015 * These are local overrides for various environment variables in Emacs.
1016 * Please do not remove this and leave it at the end of the file, where
1017 * Emacs will automagically detect them.
1018 * ---------------------------------------------------------------------
1021 * indent-tabs-mode: t
1025 * vim:noexpandtab:sw=4:ts=4: