1 /* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "vm/builtin.h"
33 #include "mm/memory.h"
36 #include "vm/global.h"
37 #include "vm/primitive.h"
39 #include "vm/jit/parse.h"
40 #include "vm/jit/show.h"
41 #include "vm/jit/stack.h"
42 #include "vm/jit/verify/typecheck-common.h"
45 /* this #if runs over the whole file: */
46 #if defined(ENABLE_VERIFIER)
48 typedef typedescriptor_t verifier_slot_t;
50 #if defined(TYPECHECK_VERBOSE)
51 static void typecheck_stackbased_show_state(verifier_state *state,
52 typedescriptor *stack,
53 typedescriptor *stackfloor,
58 #define CHECK_STACK_DEPTH(d) \
59 if (((u1*)stack - (u1*)stackfloor) \
60 < (((d)-1) * (int)sizeof(verifier_slot_t))) \
61 goto throw_stack_underflow;
63 /* XXX don't need to check against ACONST for every ICMD */
64 #define CHECK_STACK_SPACE(d) \
65 if (((u1*)STATE->stackceiling - (u1*)stack) \
66 < (((d)+1) * (int)sizeof(verifier_slot_t))) \
67 if (STATE->iptr->opc != ICMD_ACONST \
68 || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
69 goto throw_stack_overflow;
71 #define CHECK_STACK_TYPE(s, t) \
72 if ((s).type != (t)) \
73 goto throw_stack_type_error;
76 #define CHECK_LOCAL_TYPE(index, t) \
78 if (state.locals[(index)].type != (t)) \
79 goto throw_local_type_error; \
81 STATE->topjsr->usedlocals[(index)] = 1; \
82 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
83 STATE->topjsr->usedlocals[(index) + 1] = 1; \
87 #define STORE_LOCAL(t, index) \
89 state.locals[(index)].type = (t); \
90 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
91 state.locals[(index-1)].type = TYPE_VOID; \
93 STATE->topjsr->usedlocals[(index)] = 1; \
97 #define STORE_LOCAL_2_WORD(t, index) \
99 STORE_LOCAL(t, index); \
100 state.locals[(index)+1].type = TYPE_VOID; \
102 STATE->topjsr->usedlocals[(index)] = 1; \
105 #define VERIFY_ERROR(msg) \
107 LOG1("VerifyError: %s", msg); \
108 exceptions_throw_verifyerror(STATE->m, msg); \
112 #define IS_CAT1(slot) \
113 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
115 #define IS_CAT2(slot) \
116 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
118 #define CHECK_CAT1(slot) \
120 if (!IS_CAT1(slot)) \
121 goto throw_stack_category_error; \
124 #define CHECK_CAT2(slot) \
126 if (!IS_CAT2(slot)) \
127 goto throw_stack_category_error; \
130 #define COPY_SLOT(s, d) \
131 do { (d) = (s); } while (0)
133 #define REACH_BLOCK(target) \
135 if (!typecheck_stackbased_reach(STATE, (target), stack, \
136 (stack - stackfloor) + 1)) \
140 #define REACH(target) \
142 REACH_BLOCK((target).block); \
151 /* XXX should reuse typevector code */
152 static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
153 typedescriptor_t *dst,
157 bool changed = false;
160 typedescriptor_t *a = dst;
161 typedescriptor_t *b = y;
163 if (a->type != TYPE_VOID && a->type != b->type) {
167 else if (a->type == TYPE_ADR) {
168 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
169 /* 'a' is a returnAddress */
170 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
171 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
172 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
179 /* 'a' is a reference */
180 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
185 /* two reference types are merged. There cannot be */
186 /* a merge error. In the worst case we get j.l.O. */
187 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
188 if (r == typecheck_FAIL)
200 static typecheck_result typecheck_stackbased_merge(verifier_state *state,
201 basicblock *destblock,
202 typedescriptor_t *stack,
207 typedescriptor_t *stackfloor;
208 typedescriptor_t *sp;
209 typedescriptor_t *dp;
211 bool changed = false;
213 destidx = destblock->nr;
215 if (stackdepth != state->indepth[destidx]) {
216 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
217 return typecheck_FAIL;
220 stackfloor = stack - (stackdepth - 1);
223 dp = state->startstack + (destidx * state->m->maxstack);
225 for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
226 if (sp->type != dp->type) {
227 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
228 return typecheck_FAIL;
230 if (dp->type == TYPE_ADR) {
231 if (TYPEINFO_IS_PRIMITIVE(dp->typeinfo)) {
232 /* dp has returnAddress type */
233 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
234 if (TYPEINFO_RETURNADDRESS(dp->typeinfo) != TYPEINFO_RETURNADDRESS(sp->typeinfo)) {
235 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
236 return typecheck_FAIL;
240 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
241 return typecheck_FAIL;
245 /* dp has reference type */
246 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
247 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
248 return typecheck_FAIL;
250 r = typeinfo_merge(state->m,&(dp->typeinfo),&(sp->typeinfo));
251 if (r == typecheck_FAIL)
258 dp = state->startlocals + (destidx * state->numlocals);
259 r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
260 if (r == typecheck_FAIL)
267 static bool typecheck_stackbased_reach(verifier_state *state,
268 basicblock *destblock,
269 typedescriptor_t *stack,
272 bool changed = false;
277 if (destblock->flags == BBTYPECHECK_UNDEF) {
278 /* The destblock has never been reached before */
280 TYPECHECK_COUNT(stat_copied);
281 LOG1("block L%03d reached first time",destblock->nr); LOGSTR("\t");
282 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
284 state->indepth[destblock->nr] = stackdepth;
286 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
287 stack - (stackdepth - 1),
291 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
299 /* The destblock has already been reached before */
301 TYPECHECK_COUNT(stat_merged);
302 LOG1("block L%03d reached before", destblock->nr); LOGSTR("\t");
303 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
305 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
306 if (r == typecheck_FAIL)
310 TYPECHECK_COUNTIF(changed,stat_merging_changed);
315 destblock->flags = BBTYPECHECK_REACHED;
316 /* XXX is this check ok? */
317 if (destblock->nr <= state->bptr->nr) {
319 state->repeat = true;
326 /* typecheck_stackbased_verify_fieldaccess *************************************
328 Verify an ICMD_{GET,PUT}{STATIC,FIELD}
331 state............the current state of the verifier
332 instance.........the instance slot, or NULL
333 value............the value slot, or NULL
334 stack............stack after popping the arguments
337 stack pointer....successful verification,
338 NULL.............an exception has been thrown.
340 *******************************************************************************/
342 static typedescriptor_t *typecheck_stackbased_verify_fieldaccess(
343 verifier_state *state,
344 typedescriptor_t *instance,
345 typedescriptor_t *value,
346 typedescriptor_t *stack)
352 #define TYPECHECK_STACKBASED
353 #define EXCEPTION do { return NULL; } while (0)
355 #include <typecheck-fields.inc>
358 #undef TYPECHECK_STACKBASED
362 throw_stack_overflow:
363 LOG("STACK OVERFLOW!");
364 exceptions_throw_verifyerror(state->m, "Stack size too large");
368 static bool typecheck_stackbased_verify_invocation(verifier_state *state,
369 typedescriptor_t *stack,
370 typedescriptor_t *stackfloor)
374 typedescriptor_t *dv;
376 /* check stack depth */
378 /* XXX parse params */
380 INSTRUCTION_GET_METHODDESC(state->iptr, md);
382 paramslots = md->paramslots;
384 if ((stack - stackfloor) + 1 < paramslots) {
385 exceptions_throw_verifyerror(state->m,
386 "Trying to pop operand of an empty stack");
390 dv = stack - (paramslots - 1);
392 #define TYPECHECK_STACKBASED
394 #include <typecheck-invoke.inc>
396 #undef TYPECHECK_STACKBASED
401 static bool typecheck_stackbased_verify_builtin(verifier_state *state,
402 typedescriptor_t *stack,
403 typedescriptor_t *stackfloor)
406 typedescriptor_t *dv;
408 /* check stack depth */
410 /* XXX parse params */
412 paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
414 if ((stack - stackfloor) + 1 < paramslots) {
415 exceptions_throw_verifyerror(state->m,
416 "Trying to pop operand of an empty stack");
420 dv = stack - (paramslots - 1);
422 #define TYPECHECK_STACKBASED
424 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
425 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
426 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
427 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
428 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
429 #include <typecheck-builtins.inc>
431 #undef TYPECHECK_STACKBASED
435 throw_stack_type_error:
436 exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
440 static bool typecheck_stackbased_multianewarray(verifier_state *state,
441 typedescriptor_t *stack,
442 typedescriptor_t *stackfloor)
444 /* XXX recombine with verify_multianewarray */
446 classinfo *arrayclass;
447 arraydescriptor *desc;
449 typedescriptor_t *sp;
450 typedescriptor_t *dst;
452 /* destination slot */
454 i = state->iptr->s1.argcount;
458 /* check the array lengths on the stack */
460 if ((stack - stackfloor) + 1 < i) {
461 exceptions_throw_verifyerror(state->m,
462 "Trying to pop operand of an empty stack");
467 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
469 for (sp = dst; sp <= stack; ++sp) {
470 if (sp->type != TYPE_INT) {
471 exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
476 /* check array descriptor */
478 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
479 /* the array class reference has already been resolved */
480 arrayclass = state->iptr->sx.s23.s3.c.cls;
482 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
483 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
484 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
485 if (desc->dimension < state->iptr->s1.argcount)
486 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
488 /* set the array type of the result */
489 typeinfo_init_classinfo(&(dst->typeinfo), arrayclass);
493 constant_classref *cr;
495 /* the array class reference is still unresolved */
496 /* check that the reference indicates an array class of correct dimension */
497 cr = state->iptr->sx.s23.s3.c.ref;
502 /* { the dimension of the array class == i } */
504 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
505 if (i < state->iptr->s1.argcount)
506 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
508 /* set the array type of the result */
509 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
518 static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
521 typecheck_jsr_caller_t *jc;
523 for (jc = jsr->callers; jc; jc = jc->next)
524 if (jc->callblock == bptr)
527 jc = DNEW(typecheck_jsr_caller_t);
528 jc->next = jsr->callers;
529 jc->callblock = bptr;
533 static typedescriptor_t *typecheck_stackbased_jsr(verifier_state *state,
534 typedescriptor_t *stack,
535 typedescriptor_t *stackfloor)
537 typecheck_jsr_t *jsr;
544 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
545 jsr = state->jsrinfos[tbptr->nr];
547 if (jsr && tbptr->flags == BBFINISHED) {
549 LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
551 exceptions_throw_verifyerror(state->m, "Recursive JSR");
555 assert(jsr->callers);
556 assert(jsr->callers->callblock);
558 /* copy the stack of the RET edge */
560 MCOPY(stackfloor, jsr->retstack, typedescriptor_t, jsr->retdepth);
561 stack = stackfloor + (jsr->retdepth - 1);
563 /* copy variables that were used in the subroutine from the RET edge */
565 for (i=0; i<state->numlocals; ++i)
566 if (jsr->usedlocals[i])
567 state->locals[i] = jsr->retlocals[i];
569 /* reach the following block */
571 if (!typecheck_stackbased_reach(state, state->bptr->next, stack,
572 (stack - stackfloor) + 1))
577 LOG1("first JSR to block L%03d", tbptr->nr);
579 jsr = DNEW(typecheck_jsr_t);
580 state->jsrinfos[tbptr->nr] = jsr;
582 jsr->blockflags = DMNEW(char, state->basicblockcount);
583 jsr->retblock = NULL;
585 jsr->usedlocals = DMNEW(char, state->numlocals);
586 MZERO(jsr->usedlocals, char, state->numlocals);
587 jsr->retlocals = DMNEW(typedescriptor_t, state->numlocals);
588 jsr->retstack = DMNEW(typedescriptor_t, state->m->maxstack);
592 LOG1("re-analysing JSR to block L%03d", tbptr->nr);
596 jsr->next = state->topjsr;
599 assert(state->iptr->sx.s23.s3.jsrtarget.block->flags == BBTYPECHECK_REACHED);
601 tbptr->flags = BBFINISHED;
603 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
604 jsr->blockflags[tbptr->nr] = tbptr->flags;
606 if (tbptr->flags == BBTYPECHECK_REACHED)
607 tbptr->flags = BBFINISHED;
610 state->iptr->sx.s23.s3.jsrtarget.block->flags = BBTYPECHECK_REACHED;
613 /* register this block as a caller, if not already done */
615 typecheck_stackbased_add_jsr_caller(jsr, state->bptr);
620 static bool typecheck_stackbased_ret(verifier_state *state,
621 typedescriptor_t *stack,
622 typedescriptor_t *stackfloor)
625 typecheck_jsr_caller_t *jsrcaller;
626 typecheck_jsr_t *jsr;
629 /* get the subroutine we are RETurning from */
631 tbptr = TYPEINFO_RETURNADDRESS(state->locals[state->iptr->s1.varindex].typeinfo);
633 exceptions_throw_verifyerror(state->m, "Illegal RET");
637 LOG1("RET from subroutine L%03d", tbptr->nr);
638 jsr = state->jsrinfos[tbptr->nr];
641 /* check against recursion */
644 exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
648 /* check against multiple RETs for one subroutine */
650 if (jsr->retblock && jsr->retblock != state->bptr) {
651 exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
655 /* store data-flow of the RET edge */
657 jsr->retblock = state->bptr;
658 jsr->retdepth = (stack - stackfloor) + 1;
659 MCOPY(jsr->retstack, stackfloor, typedescriptor_t, jsr->retdepth);
660 MCOPY(jsr->retlocals, state->locals, typedescriptor_t, state->numlocals);
662 /* invalidate the returnAddress used by this RET */
663 /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
665 for (i=0; i<state->numlocals; ++i) {
666 typedescriptor_t *lc = &(jsr->retlocals[i]);
667 if (TYPE_IS_RETURNADDRESS(lc->type, lc->typeinfo))
668 if (TYPEINFO_RETURNADDRESS(lc->typeinfo) == tbptr) {
669 LOG1("invalidating returnAddress in local %d", i);
670 TYPEINFO_INIT_RETURNADDRESS(lc->typeinfo, NULL);
674 /* touch all callers of the subroutine, so they are analysed again */
676 for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
677 tbptr = jsrcaller->callblock;
678 LOG1("touching caller L%03d from RET", tbptr->nr);
679 assert(jsr->blockflags[tbptr->nr] >= BBFINISHED);
680 jsr->blockflags[tbptr->nr] = BBTYPECHECK_REACHED; /* XXX repeat? */
686 bool typecheck_stackbased(jitdata *jd)
688 register verifier_slot_t *stack;
689 verifier_slot_t *stackfloor;
694 verifier_slot_t temp;
695 branch_target_t *table;
696 lookup_target_t *lookup;
699 verifier_slot_t *dst;
700 verifier_state state;
703 typedescriptor_t exstack;
706 DOLOG( show_method(jd, SHOW_PARSE); );
708 /* initialize verifier state */
713 state.basicblocks = jd->basicblocks;
714 state.basicblockcount = jd->basicblockcount;
716 # define STATE (&state)
718 /* check that the basicblock numbers are valid */
721 jit_check_basicblock_numbers(jd);
724 /* check if this method is an instance initializer method */
726 state.initmethod = (state.m->name == utf_init);
728 /* allocate parameter descriptors if necessary */
730 if (!state.m->parseddesc->params)
731 if (!descriptor_params_from_paramtypes(state.m->parseddesc,state.m->flags))
734 /* allocate the stack buffers */
736 stackfloor = DMNEW(verifier_slot_t, state.m->maxstack + 1);
737 state.stackceiling = stackfloor + state.m->maxstack;
738 stack = stackfloor - 1;
739 state.indepth = DMNEW(s4, state.basicblockcount);
740 state.startstack = DMNEW(verifier_slot_t, state.m->maxstack * state.basicblockcount);
742 /* allocate the local variables buffers */
744 state.numlocals = state.m->maxlocals;
745 state.validlocals = state.m->maxlocals;
746 if (state.initmethod)
747 state.numlocals++; /* extra marker variable */
749 state.locals = DMNEW(verifier_slot_t, state.numlocals);
750 state.startlocals = DMNEW(verifier_slot_t, state.numlocals * state.basicblockcount);
752 /* allocate the buffer of active exception handlers */
754 state.handlers = DMNEW(exception_entry*, state.jd->exceptiontablelength + 1);
756 /* initialize instack of exception handlers */
758 exstack.type = TYPE_ADR;
759 typeinfo_init_classinfo(&(exstack.typeinfo),
760 class_java_lang_Throwable); /* changed later */
762 LOG("Exception handler stacks set.\n");
764 /* initialize jsr info buffer */
766 state.jsrinfos = DMNEW(typecheck_jsr_t *, state.basicblockcount);
767 MZERO(state.jsrinfos, typecheck_jsr_t *, state.basicblockcount);
769 /* initialize stack of first block */
771 state.indepth[0] = 0;
773 /* initialize locals of first block */
775 /* if this is an instance method initialize the "this" ref type */
777 if (!(state.m->flags & ACC_STATIC)) {
778 if (state.validlocals < 1)
779 VERIFY_ERROR("Not enough local variables for method arguments");
780 dst = state.startlocals;
781 dst->type = TYPE_ADR;
782 if (state.initmethod)
783 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo, NULL);
785 typeinfo_init_classinfo(&(dst->typeinfo), state.m->clazz);
790 LOG("'this' argument set.\n");
792 len = typedescriptors_init_from_methoddesc(state.startlocals + skip,
794 state.validlocals, true, skip, &state.returntype);
798 /* set remaining locals to void */
800 for (i = skip + len; i<state.numlocals; ++i)
801 state.startlocals[i].type = TYPE_VOID;
803 /* initialize block flags */
805 typecheck_init_flags(&state, BBUNDEF);
807 /* iterate until fixpoint reached */
811 state.repeat = false;
813 /* iterate over the basic blocks */
815 for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
817 if (state.bptr->flags != BBTYPECHECK_REACHED)
820 DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
822 /* mark this block as analysed */
824 state.bptr->flags = BBFINISHED;
826 /* determine the active exception handlers for this block */
827 /* XXX could use a faster algorithm with sorted lists or */
829 /* XXX reuse code from variables based verifer? */
831 for (ex = STATE->jd->exceptiontable; ex ; ex = ex->down) {
832 if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
833 LOG1("\tactive handler L%03d", ex->handler->nr);
834 STATE->handlers[len++] = ex;
837 STATE->handlers[len] = NULL;
839 /* initialize the locals */
842 state.startlocals + (state.bptr->nr * state.numlocals),
843 verifier_slot_t, state.numlocals);
845 /* initialize the stack */
847 len = state.indepth[state.bptr->nr];
850 state.startstack + (state.bptr->nr * state.m->maxstack),
851 verifier_slot_t, len);
853 stack = stackfloor + (len - 1);
855 /* iterate over the instructions in this block */
857 state.iptr = state.bptr->iinstr;
858 len = state.bptr->icount;
860 superblockend = false;
862 for (; len--; state.iptr++) {
867 DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
869 switch (state.iptr->opc) {
870 #define TYPECHECK_STACKBASED 1
871 #define STATE (&state)
872 #define IPTR state.iptr
873 #define BPTR state.bptr
874 #define METHOD state.m
875 #define LOCAL_SLOT(index) (state.locals + (index))
878 LOG("EXCEPTION THROWN!\n"); \
882 #include <typecheck-stackbased-gen.inc>
883 #undef TYPECHECK_STACKBASED
886 /* reach exception handlers for this instruction */
889 TYPECHECK_COUNT(stat_ins_maythrow);
890 TYPECHECK_MARK(STATE->stat_maythrow);
891 LOG("\treaching exception handlers");
893 while (STATE->handlers[i]) {
894 TYPECHECK_COUNT(stat_handlers_reached);
895 if (STATE->handlers[i]->catchtype.any)
896 exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
898 exstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
899 if (!typecheck_stackbased_reach(
901 STATE->handlers[i]->handler,
909 /* propagate types to the following block */
911 if (!superblockend) {
912 if (!typecheck_stackbased_reach(&state, state.bptr->next,
913 stack, stack - stackfloor + 1))
916 } /* end loop over blocks */
918 while (!state.repeat && state.topjsr) {
919 LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
921 /* propagate down used locals */
923 if (state.topjsr->next) {
924 for (i=0; i<state.numlocals; ++i)
925 state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
928 /* restore REACHED flags */
930 for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
931 assert(tbptr->flags != BBTYPECHECK_REACHED);
932 if (state.topjsr->blockflags[tbptr->nr] == BBTYPECHECK_REACHED) {
933 tbptr->flags = BBTYPECHECK_REACHED;
938 /* dactivate the subroutine */
940 state.topjsr->active = false;
941 state.topjsr = state.topjsr->next;
943 } while (state.repeat);
945 /* reset block flags */
947 typecheck_reset_flags(&state);
949 LOG("typecheck_stackbased successful");
953 throw_stack_underflow:
954 LOG("STACK UNDERFLOW!");
955 exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
958 throw_stack_overflow:
959 LOG("STACK OVERFLOW!");
960 exceptions_throw_verifyerror(state.m, "Stack size too large");
963 throw_stack_type_error:
964 LOG("STACK TYPE ERROR!");
965 exceptions_throw_verifyerror(state.m, "Mismatched stack types");
968 throw_local_type_error:
969 LOG("LOCAL TYPE ERROR!");
970 exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
973 throw_stack_category_error:
974 LOG("STACK CATEGORY ERROR!");
975 exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
980 #if defined(TYPECHECK_VERBOSE)
981 static void typecheck_stackbased_show_state(verifier_state *state,
982 typedescriptor_t *stack,
983 typedescriptor_t *stackfloor,
986 typedescriptor_t *sp;
989 LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
990 for (sp=stackfloor; sp <= stack; sp++) {
992 DOLOG( typedescriptor_print(stdout, sp); );
994 LOGSTR(" ] locals [");
995 for (i=0; i<state->numlocals; ++i) {
997 DOLOG( typedescriptor_print(stdout, state->locals + i); );
1001 if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
1003 DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
1009 #endif /* defined(ENABLE_VERIFIER) */
1013 * These are local overrides for various environment variables in Emacs.
1014 * Please do not remove this and leave it at the end of the file, where
1015 * Emacs will automagically detect them.
1016 * ---------------------------------------------------------------------
1019 * indent-tabs-mode: t
1023 * vim:noexpandtab:sw=4:ts=4: