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
38 #include "vm/global.h"
42 #include <vm/jit/stack.h>
43 #include <vm/jit/show.h>
44 #include <typecheck-common.h>
46 /* this #if runs over the whole file: */
47 #if defined(ENABLE_VERIFIER)
49 typedef typedescriptor verifier_slot_t;
51 #if defined(TYPECHECK_VERBOSE)
52 static void typecheck_stackbased_show_state(verifier_state *state,
53 typedescriptor *stack,
54 typedescriptor *stackfloor,
59 #define CHECK_STACK_DEPTH(d) \
60 if (((u1*)stack - (u1*)stackfloor) < (((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*)stackceiling - (u1*)stack) < (((d+1)) * (int)sizeof(verifier_slot_t)))\
66 if (IPTR->opc != ICMD_ACONST || INSTRUCTION_MUST_CHECK(IPTR))\
67 goto throw_stack_overflow;
69 #define CHECK_STACK_TYPE(s, t) \
70 if ((s).type != (t)) \
71 goto throw_stack_type_error;
74 #define CHECK_LOCAL_TYPE(index, t) \
76 if (state.locals[(index)].type != (t)) \
77 goto throw_local_type_error; \
79 STATE->topjsr->usedlocals[(index)] = 1; \
80 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
81 STATE->topjsr->usedlocals[(index) + 1] = 1; \
85 #define STORE_LOCAL(t, index) \
87 state.locals[(index)].type = (t); \
88 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
89 state.locals[(index-1)].type = TYPE_VOID; \
91 STATE->topjsr->usedlocals[(index)] = 1; \
95 #define STORE_LOCAL_2_WORD(t, index) \
97 STORE_LOCAL(t, index); \
98 state.locals[(index)+1].type = TYPE_VOID; \
100 STATE->topjsr->usedlocals[(index)] = 1; \
103 #define VERIFY_ERROR(msg) \
105 LOG1("VerifyError: %s", msg); \
106 exceptions_throw_verifyerror(state.m, msg); \
110 #define IS_CAT1(slot) \
111 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
113 #define IS_CAT2(slot) \
114 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
116 #define CHECK_CAT1(slot) \
118 if (!IS_CAT1(slot)) \
119 goto throw_stack_category_error; \
122 #define CHECK_CAT2(slot) \
124 if (!IS_CAT2(slot)) \
125 goto throw_stack_category_error; \
128 #define COPY_SLOT(s, d) \
129 do { (d) = (s); } while (0)
131 #define REACH_BLOCK(target) \
133 if (!typecheck_stackbased_reach(STATE, (target), stack, (stack - stackfloor) + 1))\
137 #define REACH(target) \
139 tbptr = BLOCK_OF((target).insindex); \
140 REACH_BLOCK(tbptr); \
149 /* XXX should reuse typevector code */
150 static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
155 bool changed = false;
158 typedescriptor *a = dst;
159 typedescriptor *b = y;
161 if (a->type != TYPE_VOID && a->type != b->type) {
165 else if (a->type == TYPE_ADR) {
166 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
167 /* 'a' is a returnAddress */
168 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
169 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
170 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
177 /* 'a' is a reference */
178 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
183 /* two reference types are merged. There cannot be */
184 /* a merge error. In the worst case we get j.l.O. */
185 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
186 if (r == typecheck_FAIL)
198 static typecheck_result typecheck_stackbased_merge(verifier_state *state,
199 basicblock *destblock,
200 typedescriptor *stack,
205 typedescriptor *stackfloor;
209 bool changed = false;
211 destidx = destblock->nr;
213 if (stackdepth != state->indepth[destidx]) {
214 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
215 return typecheck_FAIL;
218 stackfloor = stack - (stackdepth - 1);
221 dp = state->startstack + (destidx * state->m->maxstack);
223 for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
224 if (sp->type != dp->type) {
225 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
226 return typecheck_FAIL;
228 if (dp->type == TYPE_ADR) {
229 if (TYPEINFO_IS_PRIMITIVE(dp->typeinfo)) {
230 /* dp has returnAddress type */
231 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
232 if (TYPEINFO_RETURNADDRESS(dp->typeinfo) != TYPEINFO_RETURNADDRESS(sp->typeinfo)) {
233 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
234 return typecheck_FAIL;
238 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
239 return typecheck_FAIL;
243 /* dp has reference type */
244 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
245 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
246 return typecheck_FAIL;
248 r = typeinfo_merge(state->m,&(dp->typeinfo),&(sp->typeinfo));
249 if (r == typecheck_FAIL)
256 dp = state->startlocals + (destidx * state->numlocals);
257 r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
258 if (r == typecheck_FAIL)
265 static bool typecheck_stackbased_reach(verifier_state *state,
266 basicblock *destblock,
267 typedescriptor *stack,
270 bool changed = false;
275 if (destblock->flags == BBTYPECHECK_UNDEF) {
276 /* The destblock has never been reached before */
278 TYPECHECK_COUNT(stat_copied);
279 LOG1("block L%03d reached first time",destblock->nr); LOGSTR("\t");
280 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
282 state->indepth[destblock->nr] = stackdepth;
284 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
285 stack - (stackdepth - 1),
289 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
297 /* The destblock has already been reached before */
299 TYPECHECK_COUNT(stat_merged);
300 LOG1("block L%03d reached before", destblock->nr); LOGSTR("\t");
301 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
303 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
304 if (r == typecheck_FAIL)
308 TYPECHECK_COUNTIF(changed,stat_merging_changed);
313 destblock->flags = BBTYPECHECK_REACHED;
314 /* XXX is this check ok? */
315 if (destblock->nr <= state->bptr->nr) {
317 state->repeat = true;
324 /* typecheck_stackbased_verify_fieldaccess *************************************
326 Verify an ICMD_{GET,PUT}{STATIC,FIELD}
329 state............the current state of the verifier
330 instance.........the instance slot, or NULL
331 value............the value slot, or NULL
332 stack............stack after popping the arguments
335 stack pointer....successful verification,
336 NULL.............an exception has been thrown.
338 *******************************************************************************/
340 static typedescriptor *typecheck_stackbased_verify_fieldaccess(
341 verifier_state *state,
342 typedescriptor *instance,
343 typedescriptor *value,
344 typedescriptor *stack)
350 #define TYPECHECK_STACKBASED
351 #define EXCEPTION do { return NULL; } while (0)
352 #include <typecheck-fields.inc>
354 #undef TYPECHECK_STACKBASED
359 static bool typecheck_stackbased_verify_invocation(verifier_state *state,
360 typedescriptor *stack,
361 typedescriptor *stackfloor)
367 /* check stack depth */
369 /* XXX parse params */
371 INSTRUCTION_GET_METHODDESC(state->iptr, md);
373 paramslots = md->paramslots;
375 if ((stack - stackfloor) + 1 < paramslots) {
376 exceptions_throw_verifyerror(state->m, "Trying to pop operand of an empty stack");
380 dv = stack - (paramslots - 1);
382 #define TYPECHECK_STACKBASED
384 #include <typecheck-invoke.inc>
386 #undef TYPECHECK_STACKBASED
391 static bool typecheck_stackbased_verify_builtin(verifier_state *state,
392 typedescriptor *stack,
393 typedescriptor *stackfloor)
398 /* check stack depth */
400 /* XXX parse params */
402 paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
404 if ((stack - stackfloor) + 1 < paramslots) {
405 exceptions_throw_verifyerror(state->m, "Trying to pop operand of an empty stack");
409 dv = stack - (paramslots - 1);
411 #define TYPECHECK_STACKBASED
413 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
414 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
415 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
416 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
417 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
418 #include <typecheck-builtins.inc>
420 #undef TYPECHECK_STACKBASED
424 throw_stack_type_error:
425 exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
429 static bool typecheck_stackbased_multianewarray(verifier_state *state,
430 typedescriptor *stack,
431 typedescriptor *stackfloor)
433 /* XXX recombine with verify_multianewarray */
435 classinfo *arrayclass;
436 arraydescriptor *desc;
441 /* destination slot */
443 i = state->iptr->s1.argcount;
447 /* check the array lengths on the stack */
449 if ((stack - stackfloor) + 1 < i) {
450 exceptions_throw_verifyerror(state->m, "Trying to pop operand of an empty stack");
455 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
457 for (sp = dst; sp <= stack; ++sp) {
458 if (sp->type != TYPE_INT) {
459 exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
464 /* check array descriptor */
466 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
467 /* the array class reference has already been resolved */
468 arrayclass = state->iptr->sx.s23.s3.c.cls;
470 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
471 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
472 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
473 if (desc->dimension < state->iptr->s1.argcount)
474 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
476 /* set the array type of the result */
477 typeinfo_init_classinfo(&(dst->typeinfo), arrayclass);
481 constant_classref *cr;
483 /* the array class reference is still unresolved */
484 /* check that the reference indicates an array class of correct dimension */
485 cr = state->iptr->sx.s23.s3.c.ref;
490 /* { the dimension of the array class == i } */
492 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
493 if (i < state->iptr->s1.argcount)
494 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
496 /* set the array type of the result */
497 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
506 static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
509 typecheck_jsr_caller_t *jc;
511 for (jc = jsr->callers; jc; jc = jc->next)
512 if (jc->callblock == bptr)
515 jc = DNEW(typecheck_jsr_caller_t);
516 jc->next = jsr->callers;
517 jc->callblock = bptr;
521 static typedescriptor *typecheck_stackbased_jsr(verifier_state *state,
522 typedescriptor *stack,
523 typedescriptor *stackfloor)
525 typecheck_jsr_t *jsr;
532 tbptr = BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex);
533 jsr = state->jsrinfos[tbptr->nr];
535 if (jsr && tbptr->flags == BBFINISHED) {
537 LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
539 exceptions_throw_verifyerror(state->m, "Recursive JSR");
543 assert(jsr->callers);
544 assert(jsr->callers->callblock);
546 /* copy the stack of the RET edge */
548 MCOPY(stackfloor, jsr->retstack, typedescriptor, jsr->retdepth);
549 stack = stackfloor + (jsr->retdepth - 1);
551 /* copy variables that were used in the subroutine from the RET edge */
553 for (i=0; i<state->numlocals; ++i)
554 if (jsr->usedlocals[i])
555 state->locals[i] = jsr->retlocals[i];
557 /* reach the following block */
559 if (!typecheck_stackbased_reach(state, state->bptr->next, stack, (stack - stackfloor) + 1))
564 LOG1("first JSR to block L%03d", tbptr->nr);
566 jsr = DNEW(typecheck_jsr_t);
567 state->jsrinfos[tbptr->nr] = jsr;
569 jsr->blockflags = DMNEW(char, state->basicblockcount);
570 jsr->retblock = NULL;
572 jsr->usedlocals = DMNEW(char, state->numlocals);
573 MZERO(jsr->usedlocals, char, state->numlocals);
574 jsr->retlocals = DMNEW(typedescriptor, state->numlocals);
575 jsr->retstack = DMNEW(typedescriptor, state->m->maxstack);
579 LOG1("re-analysing JSR to block L%03d", tbptr->nr);
583 jsr->next = state->topjsr;
587 assert(BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex)->flags == BBTYPECHECK_REACHED);
588 tbptr->flags = BBFINISHED;
589 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
590 jsr->blockflags[tbptr->nr] = tbptr->flags;
591 if (tbptr->flags == BBTYPECHECK_REACHED)
592 tbptr->flags = BBFINISHED;
594 BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex)->flags = BBTYPECHECK_REACHED;
597 /* register this block as a caller, if not already done */
599 typecheck_stackbased_add_jsr_caller(jsr, state->bptr);
604 static bool typecheck_stackbased_ret(verifier_state *state,
605 typedescriptor *stack,
606 typedescriptor *stackfloor)
609 typecheck_jsr_caller_t *jsrcaller;
610 typecheck_jsr_t *jsr;
613 /* get the subroutine we are RETurning from */
615 tbptr = TYPEINFO_RETURNADDRESS(state->locals[state->iptr->s1.varindex].typeinfo);
617 exceptions_throw_verifyerror(state->m, "Illegal RET");
621 LOG1("RET from subroutine L%03d", tbptr->nr);
622 jsr = state->jsrinfos[tbptr->nr];
625 /* check against recursion */
628 exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
632 /* check against multiple RETs for one subroutine */
634 if (jsr->retblock && jsr->retblock != state->bptr) {
635 exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
639 /* store data-flow of the RET edge */
641 jsr->retblock = state->bptr;
642 jsr->retdepth = (stack - stackfloor) + 1;
643 MCOPY(jsr->retstack, stackfloor, typedescriptor, jsr->retdepth);
644 MCOPY(jsr->retlocals, state->locals, typedescriptor, state->numlocals);
646 /* invalidate the returnAddress used by this RET */
647 /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
649 for (i=0; i<state->numlocals; ++i) {
650 typedescriptor *lc = &(jsr->retlocals[i]);
651 if (TYPE_IS_RETURNADDRESS(lc->type, lc->typeinfo))
652 if (TYPEINFO_RETURNADDRESS(lc->typeinfo) == tbptr) {
653 LOG1("invalidating returnAddress in local %d", i);
654 TYPEINFO_INIT_RETURNADDRESS(lc->typeinfo, NULL);
658 /* touch all callers of the subroutine, so they are analysed again */
660 for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
661 tbptr = jsrcaller->callblock;
662 LOG1("touching caller L%03d from RET", tbptr->nr);
663 assert(jsr->blockflags[tbptr->nr] >= BBFINISHED);
664 jsr->blockflags[tbptr->nr] = BBTYPECHECK_REACHED; /* XXX repeat? */
670 bool typecheck_stackbased(jitdata *jd)
672 register verifier_slot_t *stack;
673 verifier_slot_t *stackfloor;
674 verifier_slot_t *stackceiling;
679 verifier_slot_t temp;
680 branch_target_t *table;
681 lookup_target_t *lookup;
683 constant_FMIref *fieldref;
685 verifier_slot_t *dst;
686 verifier_state state;
689 typedescriptor exstack;
692 DOLOG( show_method(jd, SHOW_PARSE); );
694 /* initialize verifier state */
699 state.basicblocks = jd->basicblocks;
700 state.basicblockcount = jd->basicblockcount;
702 # define STATE (&state)
704 /* check if this method is an instance initializer method */
706 state.initmethod = (state.m->name == utf_init);
708 /* allocate parameter descriptors if necessary */
710 if (!state.m->parseddesc->params)
711 if (!descriptor_params_from_paramtypes(state.m->parseddesc,state.m->flags))
714 /* allocate the stack buffers */
716 stackfloor = DMNEW(verifier_slot_t, state.m->maxstack + 1);
717 stackceiling = stackfloor + state.m->maxstack;
718 stack = stackfloor - 1;
719 state.indepth = DMNEW(s4, state.basicblockcount);
720 state.startstack = DMNEW(verifier_slot_t, state.m->maxstack * state.basicblockcount);
722 /* allocate the local variables buffers */
724 state.numlocals = state.m->maxlocals;
725 state.validlocals = state.m->maxlocals;
726 if (state.initmethod)
727 state.numlocals++; /* extra marker variable */
729 state.locals = DMNEW(verifier_slot_t, state.numlocals);
730 state.startlocals = DMNEW(verifier_slot_t, state.numlocals * state.basicblockcount);
732 /* allocate the buffer of active exception handlers */
734 state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
736 /* initialize instack of exception handlers */
738 exstack.type = TYPE_ADR;
739 typeinfo_init_classinfo(&(exstack.typeinfo),
740 class_java_lang_Throwable); /* changed later */
742 LOG("Exception handler stacks set.\n");
744 /* initialize jsr info buffer */
746 state.jsrinfos = DMNEW(typecheck_jsr_t *, state.basicblockcount);
747 MZERO(state.jsrinfos, typecheck_jsr_t *, state.basicblockcount);
749 /* initialize stack of first block */
751 state.indepth[0] = 0;
753 /* initialize locals of first block */
755 /* if this is an instance method initialize the "this" ref type */
757 if (!(state.m->flags & ACC_STATIC)) {
758 if (state.validlocals < 1)
759 VERIFY_ERROR("Not enough local variables for method arguments");
760 dst = state.startlocals;
761 dst->type = TYPE_ADR;
762 if (state.initmethod)
763 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo, NULL);
765 typeinfo_init_classinfo(&(dst->typeinfo), state.m->class);
770 LOG("'this' argument set.\n");
772 len = typedescriptors_init_from_methoddesc(state.startlocals + skip,
774 state.validlocals, true, skip, &state.returntype);
778 /* set remaining locals to void */
780 for (i = skip + len; i<state.numlocals; ++i)
781 state.startlocals[i].type = TYPE_VOID;
783 /* initialize block flags */
785 typecheck_init_flags(&state, BBUNDEF);
787 /* iterate until fixpoint reached */
791 state.repeat = false;
793 /* iterate over the basic blocks */
795 for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
797 if (state.bptr->flags != BBTYPECHECK_REACHED)
800 DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
802 /* mark this block as analysed */
804 state.bptr->flags = BBFINISHED;
806 /* determine the active exception handlers for this block */
807 /* XXX could use a faster algorithm with sorted lists or */
809 /* XXX reuse code from variables based verifer? */
811 for (ex = STATE->cd->exceptiontable; ex ; ex = ex->down) {
812 if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
813 LOG1("\tactive handler L%03d", ex->handler->nr);
814 STATE->handlers[len++] = ex;
817 STATE->handlers[len] = NULL;
819 /* initialize the locals */
822 state.startlocals + (state.bptr->nr * state.numlocals),
823 verifier_slot_t, state.numlocals);
825 /* initialize the stack */
827 len = state.indepth[state.bptr->nr];
830 state.startstack + (state.bptr->nr * state.m->maxstack),
831 verifier_slot_t, len);
833 stack = stackfloor + (len - 1);
835 /* iterate over the instructions in this block */
837 state.iptr = state.bptr->iinstr;
838 len = state.bptr->icount;
840 superblockend = false;
842 for (; len--; state.iptr++) {
847 DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
849 switch (state.iptr->opc) {
850 #define TYPECHECK_STACKBASED 1
851 #define STATE (&state)
852 #define IPTR state.iptr
853 #define BPTR state.bptr
854 #define METHOD state.m
855 #define LOCAL_SLOT(index) (state.locals + (index))
858 LOG("EXCEPTION THROWN!\n"); \
862 #include <typecheck-stackbased-gen.inc>
863 #undef TYPECHECK_STACKBASED
866 /* reach exception handlers for this instruction */
869 TYPECHECK_COUNT(stat_ins_maythrow);
870 TYPECHECK_MARK(STATE->stat_maythrow);
871 LOG("\treaching exception handlers");
873 while (STATE->handlers[i]) {
874 TYPECHECK_COUNT(stat_handlers_reached);
875 if (STATE->handlers[i]->catchtype.any)
876 exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
878 exstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
879 if (!typecheck_stackbased_reach(
881 STATE->handlers[i]->handler,
889 /* propagate types to the following block */
891 if (!superblockend) {
892 if (!typecheck_stackbased_reach(&state, state.bptr->next,
893 stack, stack - stackfloor + 1))
896 } /* end loop over blocks */
898 while (!state.repeat && state.topjsr) {
899 LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
901 /* propagate down used locals */
903 if (state.topjsr->next) {
904 for (i=0; i<state.numlocals; ++i)
905 state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
908 /* restore REACHED flags */
910 for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
911 assert(tbptr->flags != BBTYPECHECK_REACHED);
912 if (state.topjsr->blockflags[tbptr->nr] == BBTYPECHECK_REACHED) {
913 tbptr->flags = BBTYPECHECK_REACHED;
918 /* dactivate the subroutine */
920 state.topjsr->active = false;
921 state.topjsr = state.topjsr->next;
923 } while (state.repeat);
925 /* reset block flags */
927 typecheck_reset_flags(&state);
929 LOG("typecheck_stackbased successful");
933 throw_stack_underflow:
934 LOG("STACK UNDERFLOW!");
935 exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
938 throw_stack_overflow:
939 LOG("STACK OVERFLOW!");
940 exceptions_throw_verifyerror(state.m, "Stack size too large");
943 throw_stack_type_error:
944 LOG("STACK TYPE ERROR!");
945 exceptions_throw_verifyerror(state.m, "Mismatched stack types");
948 throw_local_type_error:
949 LOG("LOCAL TYPE ERROR!");
950 exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
953 throw_stack_category_error:
954 LOG("STACK CATEGORY ERROR!");
955 exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
960 #if defined(TYPECHECK_VERBOSE)
961 static void typecheck_stackbased_show_state(verifier_state *state,
962 typedescriptor *stack,
963 typedescriptor *stackfloor,
969 LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
970 for (sp=stackfloor; sp <= stack; sp++) {
972 DOLOG( typedescriptor_print(stdout, sp); );
974 LOGSTR(" ] locals [");
975 for (i=0; i<state->numlocals; ++i) {
977 DOLOG( typedescriptor_print(stdout, state->locals + i); );
981 if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
983 DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
989 #endif /* defined(ENABLE_VERIFIER) */
993 * These are local overrides for various environment variables in Emacs.
994 * Please do not remove this and leave it at the end of the file, where
995 * Emacs will automagically detect them.
996 * ---------------------------------------------------------------------
999 * indent-tabs-mode: t
1003 * vim:noexpandtab:sw=4:ts=4: