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
36 #include "vm/builtin.h"
37 #include "mm/memory.h"
40 #include "vm/global.h"
41 #include "vm/primitive.h"
43 #include "vm/jit/parse.h"
44 #include "vm/jit/show.h"
45 #include "vm/jit/stack.h"
46 #include "vm/jit/verify/typecheck-common.h"
49 /* this #if runs over the whole file: */
50 #if defined(ENABLE_VERIFIER)
52 typedef typedescriptor verifier_slot_t;
54 #if defined(TYPECHECK_VERBOSE)
55 static void typecheck_stackbased_show_state(verifier_state *state,
56 typedescriptor *stack,
57 typedescriptor *stackfloor,
62 #define CHECK_STACK_DEPTH(d) \
63 if (((u1*)stack - (u1*)stackfloor) \
64 < (((d)-1) * (int)sizeof(verifier_slot_t))) \
65 goto throw_stack_underflow;
67 /* XXX don't need to check against ACONST for every ICMD */
68 #define CHECK_STACK_SPACE(d) \
69 if (((u1*)STATE->stackceiling - (u1*)stack) \
70 < (((d)+1) * (int)sizeof(verifier_slot_t))) \
71 if (STATE->iptr->opc != ICMD_ACONST \
72 || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
73 goto throw_stack_overflow;
75 #define CHECK_STACK_TYPE(s, t) \
76 if ((s).type != (t)) \
77 goto throw_stack_type_error;
80 #define CHECK_LOCAL_TYPE(index, t) \
82 if (state.locals[(index)].type != (t)) \
83 goto throw_local_type_error; \
85 STATE->topjsr->usedlocals[(index)] = 1; \
86 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
87 STATE->topjsr->usedlocals[(index) + 1] = 1; \
91 #define STORE_LOCAL(t, index) \
93 state.locals[(index)].type = (t); \
94 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
95 state.locals[(index-1)].type = TYPE_VOID; \
97 STATE->topjsr->usedlocals[(index)] = 1; \
100 /* XXX inefficient */
101 #define STORE_LOCAL_2_WORD(t, index) \
103 STORE_LOCAL(t, index); \
104 state.locals[(index)+1].type = TYPE_VOID; \
106 STATE->topjsr->usedlocals[(index)] = 1; \
109 #define VERIFY_ERROR(msg) \
111 LOG1("VerifyError: %s", msg); \
112 exceptions_throw_verifyerror(STATE->m, msg); \
116 #define IS_CAT1(slot) \
117 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
119 #define IS_CAT2(slot) \
120 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
122 #define CHECK_CAT1(slot) \
124 if (!IS_CAT1(slot)) \
125 goto throw_stack_category_error; \
128 #define CHECK_CAT2(slot) \
130 if (!IS_CAT2(slot)) \
131 goto throw_stack_category_error; \
134 #define COPY_SLOT(s, d) \
135 do { (d) = (s); } while (0)
137 #define REACH_BLOCK(target) \
139 if (!typecheck_stackbased_reach(STATE, (target), stack, \
140 (stack - stackfloor) + 1)) \
144 #define REACH(target) \
146 REACH_BLOCK((target).block); \
155 /* XXX should reuse typevector code */
156 static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
161 bool changed = false;
164 typedescriptor *a = dst;
165 typedescriptor *b = y;
167 if (a->type != TYPE_VOID && a->type != b->type) {
171 else if (a->type == TYPE_ADR) {
172 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
173 /* 'a' is a returnAddress */
174 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
175 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
176 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
183 /* 'a' is a reference */
184 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
189 /* two reference types are merged. There cannot be */
190 /* a merge error. In the worst case we get j.l.O. */
191 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
192 if (r == typecheck_FAIL)
204 static typecheck_result typecheck_stackbased_merge(verifier_state *state,
205 basicblock *destblock,
206 typedescriptor *stack,
211 typedescriptor *stackfloor;
215 bool changed = false;
217 destidx = destblock->nr;
219 if (stackdepth != state->indepth[destidx]) {
220 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
221 return typecheck_FAIL;
224 stackfloor = stack - (stackdepth - 1);
227 dp = state->startstack + (destidx * state->m->maxstack);
229 for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
230 if (sp->type != dp->type) {
231 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
232 return typecheck_FAIL;
234 if (dp->type == TYPE_ADR) {
235 if (TYPEINFO_IS_PRIMITIVE(dp->typeinfo)) {
236 /* dp has returnAddress type */
237 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
238 if (TYPEINFO_RETURNADDRESS(dp->typeinfo) != TYPEINFO_RETURNADDRESS(sp->typeinfo)) {
239 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
240 return typecheck_FAIL;
244 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
245 return typecheck_FAIL;
249 /* dp has reference type */
250 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
251 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
252 return typecheck_FAIL;
254 r = typeinfo_merge(state->m,&(dp->typeinfo),&(sp->typeinfo));
255 if (r == typecheck_FAIL)
262 dp = state->startlocals + (destidx * state->numlocals);
263 r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
264 if (r == typecheck_FAIL)
271 static bool typecheck_stackbased_reach(verifier_state *state,
272 basicblock *destblock,
273 typedescriptor *stack,
276 bool changed = false;
281 if (destblock->flags == BBTYPECHECK_UNDEF) {
282 /* The destblock has never been reached before */
284 TYPECHECK_COUNT(stat_copied);
285 LOG1("block L%03d reached first time",destblock->nr); LOGSTR("\t");
286 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
288 state->indepth[destblock->nr] = stackdepth;
290 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
291 stack - (stackdepth - 1),
295 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
303 /* The destblock has already been reached before */
305 TYPECHECK_COUNT(stat_merged);
306 LOG1("block L%03d reached before", destblock->nr); LOGSTR("\t");
307 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
309 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
310 if (r == typecheck_FAIL)
314 TYPECHECK_COUNTIF(changed,stat_merging_changed);
319 destblock->flags = BBTYPECHECK_REACHED;
320 /* XXX is this check ok? */
321 if (destblock->nr <= state->bptr->nr) {
323 state->repeat = true;
330 /* typecheck_stackbased_verify_fieldaccess *************************************
332 Verify an ICMD_{GET,PUT}{STATIC,FIELD}
335 state............the current state of the verifier
336 instance.........the instance slot, or NULL
337 value............the value slot, or NULL
338 stack............stack after popping the arguments
341 stack pointer....successful verification,
342 NULL.............an exception has been thrown.
344 *******************************************************************************/
346 static typedescriptor *typecheck_stackbased_verify_fieldaccess(
347 verifier_state *state,
348 typedescriptor *instance,
349 typedescriptor *value,
350 typedescriptor *stack)
356 #define TYPECHECK_STACKBASED
357 #define EXCEPTION do { return NULL; } while (0)
359 #include <typecheck-fields.inc>
362 #undef TYPECHECK_STACKBASED
366 throw_stack_overflow:
367 LOG("STACK OVERFLOW!");
368 exceptions_throw_verifyerror(state->m, "Stack size too large");
372 static bool typecheck_stackbased_verify_invocation(verifier_state *state,
373 typedescriptor *stack,
374 typedescriptor *stackfloor)
380 /* check stack depth */
382 /* XXX parse params */
384 INSTRUCTION_GET_METHODDESC(state->iptr, md);
386 paramslots = md->paramslots;
388 if ((stack - stackfloor) + 1 < paramslots) {
389 exceptions_throw_verifyerror(state->m,
390 "Trying to pop operand of an empty stack");
394 dv = stack - (paramslots - 1);
396 #define TYPECHECK_STACKBASED
398 #include <typecheck-invoke.inc>
400 #undef TYPECHECK_STACKBASED
405 static bool typecheck_stackbased_verify_builtin(verifier_state *state,
406 typedescriptor *stack,
407 typedescriptor *stackfloor)
412 /* check stack depth */
414 /* XXX parse params */
416 paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
418 if ((stack - stackfloor) + 1 < paramslots) {
419 exceptions_throw_verifyerror(state->m,
420 "Trying to pop operand of an empty stack");
424 dv = stack - (paramslots - 1);
426 #define TYPECHECK_STACKBASED
428 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
429 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
430 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
431 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
432 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
433 #include <typecheck-builtins.inc>
435 #undef TYPECHECK_STACKBASED
439 throw_stack_type_error:
440 exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
444 static bool typecheck_stackbased_multianewarray(verifier_state *state,
445 typedescriptor *stack,
446 typedescriptor *stackfloor)
448 /* XXX recombine with verify_multianewarray */
450 classinfo *arrayclass;
451 arraydescriptor *desc;
456 /* destination slot */
458 i = state->iptr->s1.argcount;
462 /* check the array lengths on the stack */
464 if ((stack - stackfloor) + 1 < i) {
465 exceptions_throw_verifyerror(state->m,
466 "Trying to pop operand of an empty stack");
471 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
473 for (sp = dst; sp <= stack; ++sp) {
474 if (sp->type != TYPE_INT) {
475 exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
480 /* check array descriptor */
482 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
483 /* the array class reference has already been resolved */
484 arrayclass = state->iptr->sx.s23.s3.c.cls;
486 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
487 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
488 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
489 if (desc->dimension < state->iptr->s1.argcount)
490 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
492 /* set the array type of the result */
493 typeinfo_init_classinfo(&(dst->typeinfo), arrayclass);
497 constant_classref *cr;
499 /* the array class reference is still unresolved */
500 /* check that the reference indicates an array class of correct dimension */
501 cr = state->iptr->sx.s23.s3.c.ref;
506 /* { the dimension of the array class == i } */
508 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
509 if (i < state->iptr->s1.argcount)
510 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
512 /* set the array type of the result */
513 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
522 static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
525 typecheck_jsr_caller_t *jc;
527 for (jc = jsr->callers; jc; jc = jc->next)
528 if (jc->callblock == bptr)
531 jc = DNEW(typecheck_jsr_caller_t);
532 jc->next = jsr->callers;
533 jc->callblock = bptr;
537 static typedescriptor *typecheck_stackbased_jsr(verifier_state *state,
538 typedescriptor *stack,
539 typedescriptor *stackfloor)
541 typecheck_jsr_t *jsr;
548 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
549 jsr = state->jsrinfos[tbptr->nr];
551 if (jsr && tbptr->flags == BBFINISHED) {
553 LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
555 exceptions_throw_verifyerror(state->m, "Recursive JSR");
559 assert(jsr->callers);
560 assert(jsr->callers->callblock);
562 /* copy the stack of the RET edge */
564 MCOPY(stackfloor, jsr->retstack, typedescriptor, jsr->retdepth);
565 stack = stackfloor + (jsr->retdepth - 1);
567 /* copy variables that were used in the subroutine from the RET edge */
569 for (i=0; i<state->numlocals; ++i)
570 if (jsr->usedlocals[i])
571 state->locals[i] = jsr->retlocals[i];
573 /* reach the following block */
575 if (!typecheck_stackbased_reach(state, state->bptr->next, stack,
576 (stack - stackfloor) + 1))
581 LOG1("first JSR to block L%03d", tbptr->nr);
583 jsr = DNEW(typecheck_jsr_t);
584 state->jsrinfos[tbptr->nr] = jsr;
586 jsr->blockflags = DMNEW(char, state->basicblockcount);
587 jsr->retblock = NULL;
589 jsr->usedlocals = DMNEW(char, state->numlocals);
590 MZERO(jsr->usedlocals, char, state->numlocals);
591 jsr->retlocals = DMNEW(typedescriptor, state->numlocals);
592 jsr->retstack = DMNEW(typedescriptor, state->m->maxstack);
596 LOG1("re-analysing JSR to block L%03d", tbptr->nr);
600 jsr->next = state->topjsr;
603 assert(state->iptr->sx.s23.s3.jsrtarget.block->flags == BBTYPECHECK_REACHED);
605 tbptr->flags = BBFINISHED;
607 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
608 jsr->blockflags[tbptr->nr] = tbptr->flags;
610 if (tbptr->flags == BBTYPECHECK_REACHED)
611 tbptr->flags = BBFINISHED;
614 state->iptr->sx.s23.s3.jsrtarget.block->flags = BBTYPECHECK_REACHED;
617 /* register this block as a caller, if not already done */
619 typecheck_stackbased_add_jsr_caller(jsr, state->bptr);
624 static bool typecheck_stackbased_ret(verifier_state *state,
625 typedescriptor *stack,
626 typedescriptor *stackfloor)
629 typecheck_jsr_caller_t *jsrcaller;
630 typecheck_jsr_t *jsr;
633 /* get the subroutine we are RETurning from */
635 tbptr = TYPEINFO_RETURNADDRESS(state->locals[state->iptr->s1.varindex].typeinfo);
637 exceptions_throw_verifyerror(state->m, "Illegal RET");
641 LOG1("RET from subroutine L%03d", tbptr->nr);
642 jsr = state->jsrinfos[tbptr->nr];
645 /* check against recursion */
648 exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
652 /* check against multiple RETs for one subroutine */
654 if (jsr->retblock && jsr->retblock != state->bptr) {
655 exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
659 /* store data-flow of the RET edge */
661 jsr->retblock = state->bptr;
662 jsr->retdepth = (stack - stackfloor) + 1;
663 MCOPY(jsr->retstack, stackfloor, typedescriptor, jsr->retdepth);
664 MCOPY(jsr->retlocals, state->locals, typedescriptor, state->numlocals);
666 /* invalidate the returnAddress used by this RET */
667 /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
669 for (i=0; i<state->numlocals; ++i) {
670 typedescriptor *lc = &(jsr->retlocals[i]);
671 if (TYPE_IS_RETURNADDRESS(lc->type, lc->typeinfo))
672 if (TYPEINFO_RETURNADDRESS(lc->typeinfo) == tbptr) {
673 LOG1("invalidating returnAddress in local %d", i);
674 TYPEINFO_INIT_RETURNADDRESS(lc->typeinfo, NULL);
678 /* touch all callers of the subroutine, so they are analysed again */
680 for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
681 tbptr = jsrcaller->callblock;
682 LOG1("touching caller L%03d from RET", tbptr->nr);
683 assert(jsr->blockflags[tbptr->nr] >= BBFINISHED);
684 jsr->blockflags[tbptr->nr] = BBTYPECHECK_REACHED; /* XXX repeat? */
690 bool typecheck_stackbased(jitdata *jd)
692 register verifier_slot_t *stack;
693 verifier_slot_t *stackfloor;
698 verifier_slot_t temp;
699 branch_target_t *table;
700 lookup_target_t *lookup;
703 verifier_slot_t *dst;
704 verifier_state state;
707 typedescriptor exstack;
710 DOLOG( show_method(jd, SHOW_PARSE); );
712 /* initialize verifier state */
717 state.basicblocks = jd->basicblocks;
718 state.basicblockcount = jd->basicblockcount;
720 # define STATE (&state)
722 /* check that the basicblock numbers are valid */
725 jit_check_basicblock_numbers(jd);
728 /* check if this method is an instance initializer method */
730 state.initmethod = (state.m->name == utf_init);
732 /* allocate parameter descriptors if necessary */
734 if (!state.m->parseddesc->params)
735 if (!descriptor_params_from_paramtypes(state.m->parseddesc,state.m->flags))
738 /* allocate the stack buffers */
740 stackfloor = DMNEW(verifier_slot_t, state.m->maxstack + 1);
741 state.stackceiling = stackfloor + state.m->maxstack;
742 stack = stackfloor - 1;
743 state.indepth = DMNEW(s4, state.basicblockcount);
744 state.startstack = DMNEW(verifier_slot_t, state.m->maxstack * state.basicblockcount);
746 /* allocate the local variables buffers */
748 state.numlocals = state.m->maxlocals;
749 state.validlocals = state.m->maxlocals;
750 if (state.initmethod)
751 state.numlocals++; /* extra marker variable */
753 state.locals = DMNEW(verifier_slot_t, state.numlocals);
754 state.startlocals = DMNEW(verifier_slot_t, state.numlocals * state.basicblockcount);
756 /* allocate the buffer of active exception handlers */
758 state.handlers = DMNEW(exception_entry*, state.jd->exceptiontablelength + 1);
760 /* initialize instack of exception handlers */
762 exstack.type = TYPE_ADR;
763 typeinfo_init_classinfo(&(exstack.typeinfo),
764 class_java_lang_Throwable); /* changed later */
766 LOG("Exception handler stacks set.\n");
768 /* initialize jsr info buffer */
770 state.jsrinfos = DMNEW(typecheck_jsr_t *, state.basicblockcount);
771 MZERO(state.jsrinfos, typecheck_jsr_t *, state.basicblockcount);
773 /* initialize stack of first block */
775 state.indepth[0] = 0;
777 /* initialize locals of first block */
779 /* if this is an instance method initialize the "this" ref type */
781 if (!(state.m->flags & ACC_STATIC)) {
782 if (state.validlocals < 1)
783 VERIFY_ERROR("Not enough local variables for method arguments");
784 dst = state.startlocals;
785 dst->type = TYPE_ADR;
786 if (state.initmethod)
787 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo, NULL);
789 typeinfo_init_classinfo(&(dst->typeinfo), state.m->class);
794 LOG("'this' argument set.\n");
796 len = typedescriptors_init_from_methoddesc(state.startlocals + skip,
798 state.validlocals, true, skip, &state.returntype);
802 /* set remaining locals to void */
804 for (i = skip + len; i<state.numlocals; ++i)
805 state.startlocals[i].type = TYPE_VOID;
807 /* initialize block flags */
809 typecheck_init_flags(&state, BBUNDEF);
811 /* iterate until fixpoint reached */
815 state.repeat = false;
817 /* iterate over the basic blocks */
819 for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
821 if (state.bptr->flags != BBTYPECHECK_REACHED)
824 DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
826 /* mark this block as analysed */
828 state.bptr->flags = BBFINISHED;
830 /* determine the active exception handlers for this block */
831 /* XXX could use a faster algorithm with sorted lists or */
833 /* XXX reuse code from variables based verifer? */
835 for (ex = STATE->jd->exceptiontable; ex ; ex = ex->down) {
836 if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
837 LOG1("\tactive handler L%03d", ex->handler->nr);
838 STATE->handlers[len++] = ex;
841 STATE->handlers[len] = NULL;
843 /* initialize the locals */
846 state.startlocals + (state.bptr->nr * state.numlocals),
847 verifier_slot_t, state.numlocals);
849 /* initialize the stack */
851 len = state.indepth[state.bptr->nr];
854 state.startstack + (state.bptr->nr * state.m->maxstack),
855 verifier_slot_t, len);
857 stack = stackfloor + (len - 1);
859 /* iterate over the instructions in this block */
861 state.iptr = state.bptr->iinstr;
862 len = state.bptr->icount;
864 superblockend = false;
866 for (; len--; state.iptr++) {
871 DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
873 switch (state.iptr->opc) {
874 #define TYPECHECK_STACKBASED 1
875 #define STATE (&state)
876 #define IPTR state.iptr
877 #define BPTR state.bptr
878 #define METHOD state.m
879 #define LOCAL_SLOT(index) (state.locals + (index))
882 LOG("EXCEPTION THROWN!\n"); \
886 #include <typecheck-stackbased-gen.inc>
887 #undef TYPECHECK_STACKBASED
890 /* reach exception handlers for this instruction */
893 TYPECHECK_COUNT(stat_ins_maythrow);
894 TYPECHECK_MARK(STATE->stat_maythrow);
895 LOG("\treaching exception handlers");
897 while (STATE->handlers[i]) {
898 TYPECHECK_COUNT(stat_handlers_reached);
899 if (STATE->handlers[i]->catchtype.any)
900 exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
902 exstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
903 if (!typecheck_stackbased_reach(
905 STATE->handlers[i]->handler,
913 /* propagate types to the following block */
915 if (!superblockend) {
916 if (!typecheck_stackbased_reach(&state, state.bptr->next,
917 stack, stack - stackfloor + 1))
920 } /* end loop over blocks */
922 while (!state.repeat && state.topjsr) {
923 LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
925 /* propagate down used locals */
927 if (state.topjsr->next) {
928 for (i=0; i<state.numlocals; ++i)
929 state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
932 /* restore REACHED flags */
934 for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
935 assert(tbptr->flags != BBTYPECHECK_REACHED);
936 if (state.topjsr->blockflags[tbptr->nr] == BBTYPECHECK_REACHED) {
937 tbptr->flags = BBTYPECHECK_REACHED;
942 /* dactivate the subroutine */
944 state.topjsr->active = false;
945 state.topjsr = state.topjsr->next;
947 } while (state.repeat);
949 /* reset block flags */
951 typecheck_reset_flags(&state);
953 LOG("typecheck_stackbased successful");
957 throw_stack_underflow:
958 LOG("STACK UNDERFLOW!");
959 exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
962 throw_stack_overflow:
963 LOG("STACK OVERFLOW!");
964 exceptions_throw_verifyerror(state.m, "Stack size too large");
967 throw_stack_type_error:
968 LOG("STACK TYPE ERROR!");
969 exceptions_throw_verifyerror(state.m, "Mismatched stack types");
972 throw_local_type_error:
973 LOG("LOCAL TYPE ERROR!");
974 exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
977 throw_stack_category_error:
978 LOG("STACK CATEGORY ERROR!");
979 exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
984 #if defined(TYPECHECK_VERBOSE)
985 static void typecheck_stackbased_show_state(verifier_state *state,
986 typedescriptor *stack,
987 typedescriptor *stackfloor,
993 LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
994 for (sp=stackfloor; sp <= stack; sp++) {
996 DOLOG( typedescriptor_print(stdout, sp); );
998 LOGSTR(" ] locals [");
999 for (i=0; i<state->numlocals; ++i) {
1001 DOLOG( typedescriptor_print(stdout, state->locals + i); );
1005 if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
1007 DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
1013 #endif /* defined(ENABLE_VERIFIER) */
1017 * These are local overrides for various environment variables in Emacs.
1018 * Please do not remove this and leave it at the end of the file, where
1019 * Emacs will automagically detect them.
1020 * ---------------------------------------------------------------------
1023 * indent-tabs-mode: t
1027 * vim:noexpandtab:sw=4:ts=4: