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/parse.h>
44 #include <vm/jit/show.h>
45 #include <typecheck-common.h>
47 /* this #if runs over the whole file: */
48 #if defined(ENABLE_VERIFIER)
50 typedef typedescriptor verifier_slot_t;
52 #if defined(TYPECHECK_VERBOSE)
53 static void typecheck_stackbased_show_state(verifier_state *state,
54 typedescriptor *stack,
55 typedescriptor *stackfloor,
60 #define CHECK_STACK_DEPTH(d) \
61 if (((u1*)stack - (u1*)stackfloor) \
62 < (((d)-1) * (int)sizeof(verifier_slot_t))) \
63 goto throw_stack_underflow;
65 /* XXX don't need to check against ACONST for every ICMD */
66 #define CHECK_STACK_SPACE(d) \
67 if (((u1*)STATE->stackceiling - (u1*)stack) \
68 < (((d)+1) * (int)sizeof(verifier_slot_t))) \
69 if (STATE->iptr->opc != ICMD_ACONST \
70 || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
71 goto throw_stack_overflow;
73 #define CHECK_STACK_TYPE(s, t) \
74 if ((s).type != (t)) \
75 goto throw_stack_type_error;
78 #define CHECK_LOCAL_TYPE(index, t) \
80 if (state.locals[(index)].type != (t)) \
81 goto throw_local_type_error; \
83 STATE->topjsr->usedlocals[(index)] = 1; \
84 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
85 STATE->topjsr->usedlocals[(index) + 1] = 1; \
89 #define STORE_LOCAL(t, index) \
91 state.locals[(index)].type = (t); \
92 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
93 state.locals[(index-1)].type = TYPE_VOID; \
95 STATE->topjsr->usedlocals[(index)] = 1; \
99 #define STORE_LOCAL_2_WORD(t, index) \
101 STORE_LOCAL(t, index); \
102 state.locals[(index)+1].type = TYPE_VOID; \
104 STATE->topjsr->usedlocals[(index)] = 1; \
107 #define VERIFY_ERROR(msg) \
109 LOG1("VerifyError: %s", msg); \
110 exceptions_throw_verifyerror(STATE->m, msg); \
114 #define IS_CAT1(slot) \
115 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
117 #define IS_CAT2(slot) \
118 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
120 #define CHECK_CAT1(slot) \
122 if (!IS_CAT1(slot)) \
123 goto throw_stack_category_error; \
126 #define CHECK_CAT2(slot) \
128 if (!IS_CAT2(slot)) \
129 goto throw_stack_category_error; \
132 #define COPY_SLOT(s, d) \
133 do { (d) = (s); } while (0)
135 #define REACH_BLOCK(target) \
137 if (!typecheck_stackbased_reach(STATE, (target), stack, \
138 (stack - stackfloor) + 1)) \
142 #define REACH(target) \
144 tbptr = BLOCK_OF((target).insindex); \
145 REACH_BLOCK(tbptr); \
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 = BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex);
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;
603 assert(BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex)->flags == BBTYPECHECK_REACHED);
604 tbptr->flags = BBFINISHED;
605 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
606 jsr->blockflags[tbptr->nr] = tbptr->flags;
607 if (tbptr->flags == BBTYPECHECK_REACHED)
608 tbptr->flags = BBFINISHED;
610 BLOCK_OF(state->iptr->sx.s23.s3.jsrtarget.insindex)->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 *stack,
622 typedescriptor *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, jsr->retdepth);
660 MCOPY(jsr->retlocals, state->locals, typedescriptor, 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 *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 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->class);
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 *stack,
983 typedescriptor *stackfloor,
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: