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"
39 #include "vm/global.h"
40 #include "vm/primitive.h"
42 #include "vm/jit/parse.h"
43 #include "vm/jit/show.h"
44 #include "vm/jit/stack.h"
45 #include "vm/jit/verify/typecheck-common.h"
48 /* this #if runs over the whole file: */
49 #if defined(ENABLE_VERIFIER)
51 typedef typedescriptor verifier_slot_t;
53 #if defined(TYPECHECK_VERBOSE)
54 static void typecheck_stackbased_show_state(verifier_state *state,
55 typedescriptor *stack,
56 typedescriptor *stackfloor,
61 #define CHECK_STACK_DEPTH(d) \
62 if (((u1*)stack - (u1*)stackfloor) \
63 < (((d)-1) * (int)sizeof(verifier_slot_t))) \
64 goto throw_stack_underflow;
66 /* XXX don't need to check against ACONST for every ICMD */
67 #define CHECK_STACK_SPACE(d) \
68 if (((u1*)STATE->stackceiling - (u1*)stack) \
69 < (((d)+1) * (int)sizeof(verifier_slot_t))) \
70 if (STATE->iptr->opc != ICMD_ACONST \
71 || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
72 goto throw_stack_overflow;
74 #define CHECK_STACK_TYPE(s, t) \
75 if ((s).type != (t)) \
76 goto throw_stack_type_error;
79 #define CHECK_LOCAL_TYPE(index, t) \
81 if (state.locals[(index)].type != (t)) \
82 goto throw_local_type_error; \
84 STATE->topjsr->usedlocals[(index)] = 1; \
85 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
86 STATE->topjsr->usedlocals[(index) + 1] = 1; \
90 #define STORE_LOCAL(t, index) \
92 state.locals[(index)].type = (t); \
93 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
94 state.locals[(index-1)].type = TYPE_VOID; \
96 STATE->topjsr->usedlocals[(index)] = 1; \
100 #define STORE_LOCAL_2_WORD(t, index) \
102 STORE_LOCAL(t, index); \
103 state.locals[(index)+1].type = TYPE_VOID; \
105 STATE->topjsr->usedlocals[(index)] = 1; \
108 #define VERIFY_ERROR(msg) \
110 LOG1("VerifyError: %s", msg); \
111 exceptions_throw_verifyerror(STATE->m, msg); \
115 #define IS_CAT1(slot) \
116 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
118 #define IS_CAT2(slot) \
119 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
121 #define CHECK_CAT1(slot) \
123 if (!IS_CAT1(slot)) \
124 goto throw_stack_category_error; \
127 #define CHECK_CAT2(slot) \
129 if (!IS_CAT2(slot)) \
130 goto throw_stack_category_error; \
133 #define COPY_SLOT(s, d) \
134 do { (d) = (s); } while (0)
136 #define REACH_BLOCK(target) \
138 if (!typecheck_stackbased_reach(STATE, (target), stack, \
139 (stack - stackfloor) + 1)) \
143 #define REACH(target) \
145 REACH_BLOCK((target).block); \
154 /* XXX should reuse typevector code */
155 static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
160 bool changed = false;
163 typedescriptor *a = dst;
164 typedescriptor *b = y;
166 if (a->type != TYPE_VOID && a->type != b->type) {
170 else if (a->type == TYPE_ADR) {
171 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
172 /* 'a' is a returnAddress */
173 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
174 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
175 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
182 /* 'a' is a reference */
183 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
188 /* two reference types are merged. There cannot be */
189 /* a merge error. In the worst case we get j.l.O. */
190 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
191 if (r == typecheck_FAIL)
203 static typecheck_result typecheck_stackbased_merge(verifier_state *state,
204 basicblock *destblock,
205 typedescriptor *stack,
210 typedescriptor *stackfloor;
214 bool changed = false;
216 destidx = destblock->nr;
218 if (stackdepth != state->indepth[destidx]) {
219 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
220 return typecheck_FAIL;
223 stackfloor = stack - (stackdepth - 1);
226 dp = state->startstack + (destidx * state->m->maxstack);
228 for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
229 if (sp->type != dp->type) {
230 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
231 return typecheck_FAIL;
233 if (dp->type == TYPE_ADR) {
234 if (TYPEINFO_IS_PRIMITIVE(dp->typeinfo)) {
235 /* dp has returnAddress type */
236 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
237 if (TYPEINFO_RETURNADDRESS(dp->typeinfo) != TYPEINFO_RETURNADDRESS(sp->typeinfo)) {
238 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
239 return typecheck_FAIL;
243 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
244 return typecheck_FAIL;
248 /* dp has reference type */
249 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
250 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
251 return typecheck_FAIL;
253 r = typeinfo_merge(state->m,&(dp->typeinfo),&(sp->typeinfo));
254 if (r == typecheck_FAIL)
261 dp = state->startlocals + (destidx * state->numlocals);
262 r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
263 if (r == typecheck_FAIL)
270 static bool typecheck_stackbased_reach(verifier_state *state,
271 basicblock *destblock,
272 typedescriptor *stack,
275 bool changed = false;
280 if (destblock->flags == BBTYPECHECK_UNDEF) {
281 /* The destblock has never been reached before */
283 TYPECHECK_COUNT(stat_copied);
284 LOG1("block L%03d reached first time",destblock->nr); LOGSTR("\t");
285 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
287 state->indepth[destblock->nr] = stackdepth;
289 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
290 stack - (stackdepth - 1),
294 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
302 /* The destblock has already been reached before */
304 TYPECHECK_COUNT(stat_merged);
305 LOG1("block L%03d reached before", destblock->nr); LOGSTR("\t");
306 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
308 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
309 if (r == typecheck_FAIL)
313 TYPECHECK_COUNTIF(changed,stat_merging_changed);
318 destblock->flags = BBTYPECHECK_REACHED;
319 /* XXX is this check ok? */
320 if (destblock->nr <= state->bptr->nr) {
322 state->repeat = true;
329 /* typecheck_stackbased_verify_fieldaccess *************************************
331 Verify an ICMD_{GET,PUT}{STATIC,FIELD}
334 state............the current state of the verifier
335 instance.........the instance slot, or NULL
336 value............the value slot, or NULL
337 stack............stack after popping the arguments
340 stack pointer....successful verification,
341 NULL.............an exception has been thrown.
343 *******************************************************************************/
345 static typedescriptor *typecheck_stackbased_verify_fieldaccess(
346 verifier_state *state,
347 typedescriptor *instance,
348 typedescriptor *value,
349 typedescriptor *stack)
355 #define TYPECHECK_STACKBASED
356 #define EXCEPTION do { return NULL; } while (0)
358 #include <typecheck-fields.inc>
361 #undef TYPECHECK_STACKBASED
365 throw_stack_overflow:
366 LOG("STACK OVERFLOW!");
367 exceptions_throw_verifyerror(state->m, "Stack size too large");
371 static bool typecheck_stackbased_verify_invocation(verifier_state *state,
372 typedescriptor *stack,
373 typedescriptor *stackfloor)
379 /* check stack depth */
381 /* XXX parse params */
383 INSTRUCTION_GET_METHODDESC(state->iptr, md);
385 paramslots = md->paramslots;
387 if ((stack - stackfloor) + 1 < paramslots) {
388 exceptions_throw_verifyerror(state->m,
389 "Trying to pop operand of an empty stack");
393 dv = stack - (paramslots - 1);
395 #define TYPECHECK_STACKBASED
397 #include <typecheck-invoke.inc>
399 #undef TYPECHECK_STACKBASED
404 static bool typecheck_stackbased_verify_builtin(verifier_state *state,
405 typedescriptor *stack,
406 typedescriptor *stackfloor)
411 /* check stack depth */
413 /* XXX parse params */
415 paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
417 if ((stack - stackfloor) + 1 < paramslots) {
418 exceptions_throw_verifyerror(state->m,
419 "Trying to pop operand of an empty stack");
423 dv = stack - (paramslots - 1);
425 #define TYPECHECK_STACKBASED
427 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
428 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
429 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
430 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
431 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
432 #include <typecheck-builtins.inc>
434 #undef TYPECHECK_STACKBASED
438 throw_stack_type_error:
439 exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
443 static bool typecheck_stackbased_multianewarray(verifier_state *state,
444 typedescriptor *stack,
445 typedescriptor *stackfloor)
447 /* XXX recombine with verify_multianewarray */
449 classinfo *arrayclass;
450 arraydescriptor *desc;
455 /* destination slot */
457 i = state->iptr->s1.argcount;
461 /* check the array lengths on the stack */
463 if ((stack - stackfloor) + 1 < i) {
464 exceptions_throw_verifyerror(state->m,
465 "Trying to pop operand of an empty stack");
470 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
472 for (sp = dst; sp <= stack; ++sp) {
473 if (sp->type != TYPE_INT) {
474 exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
479 /* check array descriptor */
481 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
482 /* the array class reference has already been resolved */
483 arrayclass = state->iptr->sx.s23.s3.c.cls;
485 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
486 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
487 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
488 if (desc->dimension < state->iptr->s1.argcount)
489 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
491 /* set the array type of the result */
492 typeinfo_init_classinfo(&(dst->typeinfo), arrayclass);
496 constant_classref *cr;
498 /* the array class reference is still unresolved */
499 /* check that the reference indicates an array class of correct dimension */
500 cr = state->iptr->sx.s23.s3.c.ref;
505 /* { the dimension of the array class == i } */
507 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
508 if (i < state->iptr->s1.argcount)
509 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
511 /* set the array type of the result */
512 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
521 static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
524 typecheck_jsr_caller_t *jc;
526 for (jc = jsr->callers; jc; jc = jc->next)
527 if (jc->callblock == bptr)
530 jc = DNEW(typecheck_jsr_caller_t);
531 jc->next = jsr->callers;
532 jc->callblock = bptr;
536 static typedescriptor *typecheck_stackbased_jsr(verifier_state *state,
537 typedescriptor *stack,
538 typedescriptor *stackfloor)
540 typecheck_jsr_t *jsr;
547 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
548 jsr = state->jsrinfos[tbptr->nr];
550 if (jsr && tbptr->flags == BBFINISHED) {
552 LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
554 exceptions_throw_verifyerror(state->m, "Recursive JSR");
558 assert(jsr->callers);
559 assert(jsr->callers->callblock);
561 /* copy the stack of the RET edge */
563 MCOPY(stackfloor, jsr->retstack, typedescriptor, jsr->retdepth);
564 stack = stackfloor + (jsr->retdepth - 1);
566 /* copy variables that were used in the subroutine from the RET edge */
568 for (i=0; i<state->numlocals; ++i)
569 if (jsr->usedlocals[i])
570 state->locals[i] = jsr->retlocals[i];
572 /* reach the following block */
574 if (!typecheck_stackbased_reach(state, state->bptr->next, stack,
575 (stack - stackfloor) + 1))
580 LOG1("first JSR to block L%03d", tbptr->nr);
582 jsr = DNEW(typecheck_jsr_t);
583 state->jsrinfos[tbptr->nr] = jsr;
585 jsr->blockflags = DMNEW(char, state->basicblockcount);
586 jsr->retblock = NULL;
588 jsr->usedlocals = DMNEW(char, state->numlocals);
589 MZERO(jsr->usedlocals, char, state->numlocals);
590 jsr->retlocals = DMNEW(typedescriptor, state->numlocals);
591 jsr->retstack = DMNEW(typedescriptor, state->m->maxstack);
595 LOG1("re-analysing JSR to block L%03d", tbptr->nr);
599 jsr->next = state->topjsr;
602 assert(state->iptr->sx.s23.s3.jsrtarget.block->flags == BBTYPECHECK_REACHED);
604 tbptr->flags = BBFINISHED;
606 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
607 jsr->blockflags[tbptr->nr] = tbptr->flags;
609 if (tbptr->flags == BBTYPECHECK_REACHED)
610 tbptr->flags = BBFINISHED;
613 state->iptr->sx.s23.s3.jsrtarget.block->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: