1 /* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
3 Copyright (C) 1996-2005, 2006 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
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
42 #include "mm/memory.h"
43 #include "vm/global.h"
44 #include "vm/jit/parse.h"
45 #include "vm/jit/show.h"
46 #include "vm/jit/stack.h"
47 #include "vm/jit/verify/typecheck-common.h"
50 /* this #if runs over the whole file: */
51 #if defined(ENABLE_VERIFIER)
53 typedef typedescriptor verifier_slot_t;
55 #if defined(TYPECHECK_VERBOSE)
56 static void typecheck_stackbased_show_state(verifier_state *state,
57 typedescriptor *stack,
58 typedescriptor *stackfloor,
63 #define CHECK_STACK_DEPTH(d) \
64 if (((u1*)stack - (u1*)stackfloor) \
65 < (((d)-1) * (int)sizeof(verifier_slot_t))) \
66 goto throw_stack_underflow;
68 /* XXX don't need to check against ACONST for every ICMD */
69 #define CHECK_STACK_SPACE(d) \
70 if (((u1*)STATE->stackceiling - (u1*)stack) \
71 < (((d)+1) * (int)sizeof(verifier_slot_t))) \
72 if (STATE->iptr->opc != ICMD_ACONST \
73 || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
74 goto throw_stack_overflow;
76 #define CHECK_STACK_TYPE(s, t) \
77 if ((s).type != (t)) \
78 goto throw_stack_type_error;
81 #define CHECK_LOCAL_TYPE(index, t) \
83 if (state.locals[(index)].type != (t)) \
84 goto throw_local_type_error; \
86 STATE->topjsr->usedlocals[(index)] = 1; \
87 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
88 STATE->topjsr->usedlocals[(index) + 1] = 1; \
92 #define STORE_LOCAL(t, index) \
94 state.locals[(index)].type = (t); \
95 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
96 state.locals[(index-1)].type = TYPE_VOID; \
98 STATE->topjsr->usedlocals[(index)] = 1; \
101 /* XXX inefficient */
102 #define STORE_LOCAL_2_WORD(t, index) \
104 STORE_LOCAL(t, index); \
105 state.locals[(index)+1].type = TYPE_VOID; \
107 STATE->topjsr->usedlocals[(index)] = 1; \
110 #define VERIFY_ERROR(msg) \
112 LOG1("VerifyError: %s", msg); \
113 exceptions_throw_verifyerror(STATE->m, msg); \
117 #define IS_CAT1(slot) \
118 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
120 #define IS_CAT2(slot) \
121 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
123 #define CHECK_CAT1(slot) \
125 if (!IS_CAT1(slot)) \
126 goto throw_stack_category_error; \
129 #define CHECK_CAT2(slot) \
131 if (!IS_CAT2(slot)) \
132 goto throw_stack_category_error; \
135 #define COPY_SLOT(s, d) \
136 do { (d) = (s); } while (0)
138 #define REACH_BLOCK(target) \
140 if (!typecheck_stackbased_reach(STATE, (target), stack, \
141 (stack - stackfloor) + 1)) \
145 #define REACH(target) \
147 tbptr = BLOCK_OF((target).insindex); \
148 REACH_BLOCK(tbptr); \
157 /* XXX should reuse typevector code */
158 static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
163 bool changed = false;
166 typedescriptor *a = dst;
167 typedescriptor *b = y;
169 if (a->type != TYPE_VOID && a->type != b->type) {
173 else if (a->type == TYPE_ADR) {
174 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
175 /* 'a' is a returnAddress */
176 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
177 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
178 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
185 /* 'a' is a reference */
186 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
191 /* two reference types are merged. There cannot be */
192 /* a merge error. In the worst case we get j.l.O. */
193 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
194 if (r == typecheck_FAIL)
206 static typecheck_result typecheck_stackbased_merge(verifier_state *state,
207 basicblock *destblock,
208 typedescriptor *stack,
213 typedescriptor *stackfloor;
217 bool changed = false;
219 destidx = destblock->nr;
221 if (stackdepth != state->indepth[destidx]) {
222 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
223 return typecheck_FAIL;
226 stackfloor = stack - (stackdepth - 1);
229 dp = state->startstack + (destidx * state->m->maxstack);
231 for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
232 if (sp->type != dp->type) {
233 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
234 return typecheck_FAIL;
236 if (dp->type == TYPE_ADR) {
237 if (TYPEINFO_IS_PRIMITIVE(dp->typeinfo)) {
238 /* dp has returnAddress type */
239 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
240 if (TYPEINFO_RETURNADDRESS(dp->typeinfo) != TYPEINFO_RETURNADDRESS(sp->typeinfo)) {
241 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
242 return typecheck_FAIL;
246 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
247 return typecheck_FAIL;
251 /* dp has reference type */
252 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
253 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
254 return typecheck_FAIL;
256 r = typeinfo_merge(state->m,&(dp->typeinfo),&(sp->typeinfo));
257 if (r == typecheck_FAIL)
264 dp = state->startlocals + (destidx * state->numlocals);
265 r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
266 if (r == typecheck_FAIL)
273 static bool typecheck_stackbased_reach(verifier_state *state,
274 basicblock *destblock,
275 typedescriptor *stack,
278 bool changed = false;
283 if (destblock->flags == BBTYPECHECK_UNDEF) {
284 /* The destblock has never been reached before */
286 TYPECHECK_COUNT(stat_copied);
287 LOG1("block L%03d reached first time",destblock->nr); LOGSTR("\t");
288 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
290 state->indepth[destblock->nr] = stackdepth;
292 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
293 stack - (stackdepth - 1),
297 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
305 /* The destblock has already been reached before */
307 TYPECHECK_COUNT(stat_merged);
308 LOG1("block L%03d reached before", destblock->nr); LOGSTR("\t");
309 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
311 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
312 if (r == typecheck_FAIL)
316 TYPECHECK_COUNTIF(changed,stat_merging_changed);
321 destblock->flags = BBTYPECHECK_REACHED;
322 /* XXX is this check ok? */
323 if (destblock->nr <= state->bptr->nr) {
325 state->repeat = true;
332 /* typecheck_stackbased_verify_fieldaccess *************************************
334 Verify an ICMD_{GET,PUT}{STATIC,FIELD}
337 state............the current state of the verifier
338 instance.........the instance slot, or NULL
339 value............the value slot, or NULL
340 stack............stack after popping the arguments
343 stack pointer....successful verification,
344 NULL.............an exception has been thrown.
346 *******************************************************************************/
348 static typedescriptor *typecheck_stackbased_verify_fieldaccess(
349 verifier_state *state,
350 typedescriptor *instance,
351 typedescriptor *value,
352 typedescriptor *stack)
358 #define TYPECHECK_STACKBASED
359 #define EXCEPTION do { return NULL; } while (0)
361 #include <typecheck-fields.inc>
364 #undef TYPECHECK_STACKBASED
368 throw_stack_overflow:
369 LOG("STACK OVERFLOW!");
370 exceptions_throw_verifyerror(state->m, "Stack size too large");
374 static bool typecheck_stackbased_verify_invocation(verifier_state *state,
375 typedescriptor *stack,
376 typedescriptor *stackfloor)
382 /* check stack depth */
384 /* XXX parse params */
386 INSTRUCTION_GET_METHODDESC(state->iptr, md);
388 paramslots = md->paramslots;
390 if ((stack - stackfloor) + 1 < paramslots) {
391 exceptions_throw_verifyerror(state->m,
392 "Trying to pop operand of an empty stack");
396 dv = stack - (paramslots - 1);
398 #define TYPECHECK_STACKBASED
400 #include <typecheck-invoke.inc>
402 #undef TYPECHECK_STACKBASED
407 static bool typecheck_stackbased_verify_builtin(verifier_state *state,
408 typedescriptor *stack,
409 typedescriptor *stackfloor)
414 /* check stack depth */
416 /* XXX parse params */
418 paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
420 if ((stack - stackfloor) + 1 < paramslots) {
421 exceptions_throw_verifyerror(state->m,
422 "Trying to pop operand of an empty stack");
426 dv = stack - (paramslots - 1);
428 #define TYPECHECK_STACKBASED
430 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
431 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
432 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
433 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
434 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
435 #include <typecheck-builtins.inc>
437 #undef TYPECHECK_STACKBASED
441 throw_stack_type_error:
442 exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
446 static bool typecheck_stackbased_multianewarray(verifier_state *state,
447 typedescriptor *stack,
448 typedescriptor *stackfloor)
450 /* XXX recombine with verify_multianewarray */
452 classinfo *arrayclass;
453 arraydescriptor *desc;
458 /* destination slot */
460 i = state->iptr->s1.argcount;
464 /* check the array lengths on the stack */
466 if ((stack - stackfloor) + 1 < i) {
467 exceptions_throw_verifyerror(state->m,
468 "Trying to pop operand of an empty stack");
473 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
475 for (sp = dst; sp <= stack; ++sp) {
476 if (sp->type != TYPE_INT) {
477 exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
482 /* check array descriptor */
484 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
485 /* the array class reference has already been resolved */
486 arrayclass = state->iptr->sx.s23.s3.c.cls;
488 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
489 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
490 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
491 if (desc->dimension < state->iptr->s1.argcount)
492 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
494 /* set the array type of the result */
495 typeinfo_init_classinfo(&(dst->typeinfo), arrayclass);
499 constant_classref *cr;
501 /* the array class reference is still unresolved */
502 /* check that the reference indicates an array class of correct dimension */
503 cr = state->iptr->sx.s23.s3.c.ref;
508 /* { the dimension of the array class == i } */
510 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
511 if (i < state->iptr->s1.argcount)
512 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
514 /* set the array type of the result */
515 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
524 static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
527 typecheck_jsr_caller_t *jc;
529 for (jc = jsr->callers; jc; jc = jc->next)
530 if (jc->callblock == bptr)
533 jc = DNEW(typecheck_jsr_caller_t);
534 jc->next = jsr->callers;
535 jc->callblock = bptr;
539 static typedescriptor *typecheck_stackbased_jsr(verifier_state *state,
540 typedescriptor *stack,
541 typedescriptor *stackfloor)
543 typecheck_jsr_t *jsr;
550 tbptr = BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex);
551 jsr = state->jsrinfos[tbptr->nr];
553 if (jsr && tbptr->flags == BBFINISHED) {
555 LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
557 exceptions_throw_verifyerror(state->m, "Recursive JSR");
561 assert(jsr->callers);
562 assert(jsr->callers->callblock);
564 /* copy the stack of the RET edge */
566 MCOPY(stackfloor, jsr->retstack, typedescriptor, jsr->retdepth);
567 stack = stackfloor + (jsr->retdepth - 1);
569 /* copy variables that were used in the subroutine from the RET edge */
571 for (i=0; i<state->numlocals; ++i)
572 if (jsr->usedlocals[i])
573 state->locals[i] = jsr->retlocals[i];
575 /* reach the following block */
577 if (!typecheck_stackbased_reach(state, state->bptr->next, stack,
578 (stack - stackfloor) + 1))
583 LOG1("first JSR to block L%03d", tbptr->nr);
585 jsr = DNEW(typecheck_jsr_t);
586 state->jsrinfos[tbptr->nr] = jsr;
588 jsr->blockflags = DMNEW(char, state->basicblockcount);
589 jsr->retblock = NULL;
591 jsr->usedlocals = DMNEW(char, state->numlocals);
592 MZERO(jsr->usedlocals, char, state->numlocals);
593 jsr->retlocals = DMNEW(typedescriptor, state->numlocals);
594 jsr->retstack = DMNEW(typedescriptor, state->m->maxstack);
598 LOG1("re-analysing JSR to block L%03d", tbptr->nr);
602 jsr->next = state->topjsr;
606 assert(BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex)->flags == BBTYPECHECK_REACHED);
607 tbptr->flags = BBFINISHED;
608 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
609 jsr->blockflags[tbptr->nr] = tbptr->flags;
610 if (tbptr->flags == BBTYPECHECK_REACHED)
611 tbptr->flags = BBFINISHED;
613 BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex)->flags = BBTYPECHECK_REACHED;
616 /* register this block as a caller, if not already done */
618 typecheck_stackbased_add_jsr_caller(jsr, state->bptr);
623 static bool typecheck_stackbased_ret(verifier_state *state,
624 typedescriptor *stack,
625 typedescriptor *stackfloor)
628 typecheck_jsr_caller_t *jsrcaller;
629 typecheck_jsr_t *jsr;
632 /* get the subroutine we are RETurning from */
634 tbptr = TYPEINFO_RETURNADDRESS(state->locals[state->iptr->s1.varindex].typeinfo);
636 exceptions_throw_verifyerror(state->m, "Illegal RET");
640 LOG1("RET from subroutine L%03d", tbptr->nr);
641 jsr = state->jsrinfos[tbptr->nr];
644 /* check against recursion */
647 exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
651 /* check against multiple RETs for one subroutine */
653 if (jsr->retblock && jsr->retblock != state->bptr) {
654 exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
658 /* store data-flow of the RET edge */
660 jsr->retblock = state->bptr;
661 jsr->retdepth = (stack - stackfloor) + 1;
662 MCOPY(jsr->retstack, stackfloor, typedescriptor, jsr->retdepth);
663 MCOPY(jsr->retlocals, state->locals, typedescriptor, state->numlocals);
665 /* invalidate the returnAddress used by this RET */
666 /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
668 for (i=0; i<state->numlocals; ++i) {
669 typedescriptor *lc = &(jsr->retlocals[i]);
670 if (TYPE_IS_RETURNADDRESS(lc->type, lc->typeinfo))
671 if (TYPEINFO_RETURNADDRESS(lc->typeinfo) == tbptr) {
672 LOG1("invalidating returnAddress in local %d", i);
673 TYPEINFO_INIT_RETURNADDRESS(lc->typeinfo, NULL);
677 /* touch all callers of the subroutine, so they are analysed again */
679 for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
680 tbptr = jsrcaller->callblock;
681 LOG1("touching caller L%03d from RET", tbptr->nr);
682 assert(jsr->blockflags[tbptr->nr] >= BBFINISHED);
683 jsr->blockflags[tbptr->nr] = BBTYPECHECK_REACHED; /* XXX repeat? */
689 bool typecheck_stackbased(jitdata *jd)
691 register verifier_slot_t *stack;
692 verifier_slot_t *stackfloor;
697 verifier_slot_t temp;
698 branch_target_t *table;
699 lookup_target_t *lookup;
702 verifier_slot_t *dst;
703 verifier_state state;
706 typedescriptor exstack;
709 DOLOG( show_method(jd, SHOW_PARSE); );
711 /* initialize verifier state */
716 state.basicblocks = jd->basicblocks;
717 state.basicblockcount = jd->basicblockcount;
719 # define STATE (&state)
721 /* check that the basicblock numbers are valid */
724 jit_check_basicblock_numbers(jd);
727 /* check if this method is an instance initializer method */
729 state.initmethod = (state.m->name == utf_init);
731 /* allocate parameter descriptors if necessary */
733 if (!state.m->parseddesc->params)
734 if (!descriptor_params_from_paramtypes(state.m->parseddesc,state.m->flags))
737 /* allocate the stack buffers */
739 stackfloor = DMNEW(verifier_slot_t, state.m->maxstack + 1);
740 state.stackceiling = stackfloor + state.m->maxstack;
741 stack = stackfloor - 1;
742 state.indepth = DMNEW(s4, state.basicblockcount);
743 state.startstack = DMNEW(verifier_slot_t, state.m->maxstack * state.basicblockcount);
745 /* allocate the local variables buffers */
747 state.numlocals = state.m->maxlocals;
748 state.validlocals = state.m->maxlocals;
749 if (state.initmethod)
750 state.numlocals++; /* extra marker variable */
752 state.locals = DMNEW(verifier_slot_t, state.numlocals);
753 state.startlocals = DMNEW(verifier_slot_t, state.numlocals * state.basicblockcount);
755 /* allocate the buffer of active exception handlers */
757 state.handlers = DMNEW(exception_entry*, state.jd->exceptiontablelength + 1);
759 /* initialize instack of exception handlers */
761 exstack.type = TYPE_ADR;
762 typeinfo_init_classinfo(&(exstack.typeinfo),
763 class_java_lang_Throwable); /* changed later */
765 LOG("Exception handler stacks set.\n");
767 /* initialize jsr info buffer */
769 state.jsrinfos = DMNEW(typecheck_jsr_t *, state.basicblockcount);
770 MZERO(state.jsrinfos, typecheck_jsr_t *, state.basicblockcount);
772 /* initialize stack of first block */
774 state.indepth[0] = 0;
776 /* initialize locals of first block */
778 /* if this is an instance method initialize the "this" ref type */
780 if (!(state.m->flags & ACC_STATIC)) {
781 if (state.validlocals < 1)
782 VERIFY_ERROR("Not enough local variables for method arguments");
783 dst = state.startlocals;
784 dst->type = TYPE_ADR;
785 if (state.initmethod)
786 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo, NULL);
788 typeinfo_init_classinfo(&(dst->typeinfo), state.m->class);
793 LOG("'this' argument set.\n");
795 len = typedescriptors_init_from_methoddesc(state.startlocals + skip,
797 state.validlocals, true, skip, &state.returntype);
801 /* set remaining locals to void */
803 for (i = skip + len; i<state.numlocals; ++i)
804 state.startlocals[i].type = TYPE_VOID;
806 /* initialize block flags */
808 typecheck_init_flags(&state, BBUNDEF);
810 /* iterate until fixpoint reached */
814 state.repeat = false;
816 /* iterate over the basic blocks */
818 for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
820 if (state.bptr->flags != BBTYPECHECK_REACHED)
823 DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
825 /* mark this block as analysed */
827 state.bptr->flags = BBFINISHED;
829 /* determine the active exception handlers for this block */
830 /* XXX could use a faster algorithm with sorted lists or */
832 /* XXX reuse code from variables based verifer? */
834 for (ex = STATE->jd->exceptiontable; ex ; ex = ex->down) {
835 if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
836 LOG1("\tactive handler L%03d", ex->handler->nr);
837 STATE->handlers[len++] = ex;
840 STATE->handlers[len] = NULL;
842 /* initialize the locals */
845 state.startlocals + (state.bptr->nr * state.numlocals),
846 verifier_slot_t, state.numlocals);
848 /* initialize the stack */
850 len = state.indepth[state.bptr->nr];
853 state.startstack + (state.bptr->nr * state.m->maxstack),
854 verifier_slot_t, len);
856 stack = stackfloor + (len - 1);
858 /* iterate over the instructions in this block */
860 state.iptr = state.bptr->iinstr;
861 len = state.bptr->icount;
863 superblockend = false;
865 for (; len--; state.iptr++) {
870 DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
872 switch (state.iptr->opc) {
873 #define TYPECHECK_STACKBASED 1
874 #define STATE (&state)
875 #define IPTR state.iptr
876 #define BPTR state.bptr
877 #define METHOD state.m
878 #define LOCAL_SLOT(index) (state.locals + (index))
881 LOG("EXCEPTION THROWN!\n"); \
885 #include <typecheck-stackbased-gen.inc>
886 #undef TYPECHECK_STACKBASED
889 /* reach exception handlers for this instruction */
892 TYPECHECK_COUNT(stat_ins_maythrow);
893 TYPECHECK_MARK(STATE->stat_maythrow);
894 LOG("\treaching exception handlers");
896 while (STATE->handlers[i]) {
897 TYPECHECK_COUNT(stat_handlers_reached);
898 if (STATE->handlers[i]->catchtype.any)
899 exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
901 exstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
902 if (!typecheck_stackbased_reach(
904 STATE->handlers[i]->handler,
912 /* propagate types to the following block */
914 if (!superblockend) {
915 if (!typecheck_stackbased_reach(&state, state.bptr->next,
916 stack, stack - stackfloor + 1))
919 } /* end loop over blocks */
921 while (!state.repeat && state.topjsr) {
922 LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
924 /* propagate down used locals */
926 if (state.topjsr->next) {
927 for (i=0; i<state.numlocals; ++i)
928 state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
931 /* restore REACHED flags */
933 for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
934 assert(tbptr->flags != BBTYPECHECK_REACHED);
935 if (state.topjsr->blockflags[tbptr->nr] == BBTYPECHECK_REACHED) {
936 tbptr->flags = BBTYPECHECK_REACHED;
941 /* dactivate the subroutine */
943 state.topjsr->active = false;
944 state.topjsr = state.topjsr->next;
946 } while (state.repeat);
948 /* reset block flags */
950 typecheck_reset_flags(&state);
952 LOG("typecheck_stackbased successful");
956 throw_stack_underflow:
957 LOG("STACK UNDERFLOW!");
958 exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
961 throw_stack_overflow:
962 LOG("STACK OVERFLOW!");
963 exceptions_throw_verifyerror(state.m, "Stack size too large");
966 throw_stack_type_error:
967 LOG("STACK TYPE ERROR!");
968 exceptions_throw_verifyerror(state.m, "Mismatched stack types");
971 throw_local_type_error:
972 LOG("LOCAL TYPE ERROR!");
973 exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
976 throw_stack_category_error:
977 LOG("STACK CATEGORY ERROR!");
978 exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
983 #if defined(TYPECHECK_VERBOSE)
984 static void typecheck_stackbased_show_state(verifier_state *state,
985 typedescriptor *stack,
986 typedescriptor *stackfloor,
992 LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
993 for (sp=stackfloor; sp <= stack; sp++) {
995 DOLOG( typedescriptor_print(stdout, sp); );
997 LOGSTR(" ] locals [");
998 for (i=0; i<state->numlocals; ++i) {
1000 DOLOG( typedescriptor_print(stdout, state->locals + i); );
1004 if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
1006 DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
1012 #endif /* defined(ENABLE_VERIFIER) */
1016 * These are local overrides for various environment variables in Emacs.
1017 * Please do not remove this and leave it at the end of the file, where
1018 * Emacs will automagically detect them.
1019 * ---------------------------------------------------------------------
1022 * indent-tabs-mode: t
1026 * vim:noexpandtab:sw=4:ts=4: