1 /* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
3 Copyright (C) 1996-2011
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "vm/jit/builtin.hpp"
33 #include "mm/memory.hpp"
35 #include "vm/array.hpp"
36 #include "vm/exceptions.hpp"
37 #include "vm/global.h"
38 #include "vm/globals.hpp"
39 #include "vm/primitive.hpp"
41 #include "vm/jit/parse.hpp"
42 #include "vm/jit/show.hpp"
43 #include "vm/jit/stack.h"
44 #include "vm/jit/verify/typecheck-common.hpp"
46 #if defined(__cplusplus)
50 /* this #if runs over the whole file: */
51 #if defined(ENABLE_VERIFIER)
53 typedef typedescriptor_t verifier_slot_t;
55 #if defined(TYPECHECK_VERBOSE)
56 static void typecheck_stackbased_show_state(verifier_state *state,
57 typedescriptor *stack,
58 typedescriptor *stackfloor,
63 #define CHECK_STACK_DEPTH(d) \
64 if (((u1*)stack - (u1*)stackfloor) \
65 < (((d)-1) * (int)sizeof(verifier_slot_t))) \
66 goto throw_stack_underflow;
68 /* XXX don't need to check against ACONST for every ICMD */
69 #define CHECK_STACK_SPACE(d) \
70 if (((u1*)STATE->stackceiling - (u1*)stack) \
71 < (((d)+1) * (int)sizeof(verifier_slot_t))) \
72 if (STATE->iptr->opc != ICMD_ACONST \
73 || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
74 goto throw_stack_overflow;
76 #define CHECK_STACK_TYPE(s, t) \
77 if ((s).type != (t)) \
78 goto throw_stack_type_error;
81 #define CHECK_LOCAL_TYPE(index, t) \
83 if (state.locals[(index)].type != (t)) \
84 goto throw_local_type_error; \
86 STATE->topjsr->usedlocals[(index)] = 1; \
87 if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
88 STATE->topjsr->usedlocals[(index) + 1] = 1; \
92 #define STORE_LOCAL(t, index) \
94 state.locals[(index)].type = (t); \
95 if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
96 state.locals[(index-1)].type = TYPE_VOID; \
98 STATE->topjsr->usedlocals[(index)] = 1; \
101 /* XXX inefficient */
102 #define STORE_LOCAL_2_WORD(t, index) \
104 STORE_LOCAL(t, index); \
105 state.locals[(index)+1].type = TYPE_VOID; \
107 STATE->topjsr->usedlocals[(index)] = 1; \
110 #define VERIFY_ERROR(msg) \
112 LOG1("VerifyError: %s", msg); \
113 exceptions_throw_verifyerror(STATE->m, msg); \
117 #define IS_CAT1(slot) \
118 ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
120 #define IS_CAT2(slot) \
121 ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
123 #define CHECK_CAT1(slot) \
125 if (!IS_CAT1(slot)) \
126 goto throw_stack_category_error; \
129 #define CHECK_CAT2(slot) \
131 if (!IS_CAT2(slot)) \
132 goto throw_stack_category_error; \
135 #define COPY_SLOT(s, d) \
136 do { (d) = (s); } while (0)
138 #define REACH_BLOCK(target) \
140 if (!typecheck_stackbased_reach(STATE, (target), stack, \
141 (stack - stackfloor) + 1)) \
145 #define REACH(target) \
147 REACH_BLOCK((target).block); \
156 /* XXX should reuse typevector code */
157 static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
158 typedescriptor_t *dst,
162 bool changed = false;
165 typedescriptor_t *a = dst;
166 typedescriptor_t *b = y;
168 if (a->type != TYPE_VOID && a->type != b->type) {
172 else if (a->type == TYPE_ADR) {
173 if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
174 /* 'a' is a returnAddress */
175 if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
176 || (TYPEINFO_RETURNADDRESS(a->typeinfo)
177 != TYPEINFO_RETURNADDRESS(b->typeinfo)))
184 /* 'a' is a reference */
185 if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
190 /* two reference types are merged. There cannot be */
191 /* a merge error. In the worst case we get j.l.O. */
192 r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
193 if (r == typecheck_FAIL)
202 return (typecheck_result) changed;
205 static typecheck_result typecheck_stackbased_merge(verifier_state *state,
206 basicblock *destblock,
207 typedescriptor_t *stack,
212 typedescriptor_t *stackfloor;
213 typedescriptor_t *sp;
214 typedescriptor_t *dp;
216 bool changed = false;
218 destidx = destblock->nr;
220 if (stackdepth != state->indepth[destidx]) {
221 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
222 return typecheck_FAIL;
225 stackfloor = stack - (stackdepth - 1);
228 dp = state->startstack + (destidx * state->m->maxstack);
230 for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
231 if (sp->type != dp->type) {
232 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
233 return typecheck_FAIL;
235 if (dp->type == TYPE_ADR) {
236 if (TYPEINFO_IS_PRIMITIVE(dp->typeinfo)) {
237 /* dp has returnAddress type */
238 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
239 if (TYPEINFO_RETURNADDRESS(dp->typeinfo) != TYPEINFO_RETURNADDRESS(sp->typeinfo)) {
240 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
241 return typecheck_FAIL;
245 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
246 return typecheck_FAIL;
250 /* dp has reference type */
251 if (TYPEINFO_IS_PRIMITIVE(sp->typeinfo)) {
252 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
253 return typecheck_FAIL;
255 r = typeinfo_merge(state->m,&(dp->typeinfo),&(sp->typeinfo));
256 if (r == typecheck_FAIL)
263 dp = state->startlocals + (destidx * state->numlocals);
264 r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
265 if (r == typecheck_FAIL)
269 return (typecheck_result) changed;
272 static bool typecheck_stackbased_reach(verifier_state *state,
273 basicblock *destblock,
274 typedescriptor_t *stack,
277 bool changed = false;
282 if (destblock->flags == BBTYPECHECK_UNDEF) {
283 /* The destblock has never been reached before */
285 TYPECHECK_COUNT(stat_copied);
286 LOG1("block L%03d reached first time",destblock->nr); LOGSTR("\t");
287 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
289 state->indepth[destblock->nr] = stackdepth;
291 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
292 stack - (stackdepth - 1),
296 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
304 /* The destblock has already been reached before */
306 TYPECHECK_COUNT(stat_merged);
307 LOG1("block L%03d reached before", destblock->nr); LOGSTR("\t");
308 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
310 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
311 if (r == typecheck_FAIL)
315 TYPECHECK_COUNTIF(changed,stat_merging_changed);
320 destblock->flags = BBTYPECHECK_REACHED;
321 /* XXX is this check ok? */
322 if (destblock->nr <= state->bptr->nr) {
324 state->repeat = true;
331 /* typecheck_stackbased_verify_fieldaccess *************************************
333 Verify an ICMD_{GET,PUT}{STATIC,FIELD}
336 state............the current state of the verifier
337 instance.........the instance slot, or NULL
338 value............the value slot, or NULL
339 stack............stack after popping the arguments
342 stack pointer....successful verification,
343 NULL.............an exception has been thrown.
345 *******************************************************************************/
347 static typedescriptor_t *typecheck_stackbased_verify_fieldaccess(
348 verifier_state *state,
349 typedescriptor_t *instance,
350 typedescriptor_t *value,
351 typedescriptor_t *stack)
357 #define TYPECHECK_STACKBASED
358 #define EXCEPTION do { return NULL; } while (0)
360 #include <typecheck-fields.inc>
363 #undef TYPECHECK_STACKBASED
367 throw_stack_overflow:
368 LOG("STACK OVERFLOW!");
369 exceptions_throw_verifyerror(state->m, "Stack size too large");
373 static bool typecheck_stackbased_verify_invocation(verifier_state *state,
374 typedescriptor_t *stack,
375 typedescriptor_t *stackfloor)
379 typedescriptor_t *dv;
381 /* check stack depth */
383 /* XXX parse params */
385 INSTRUCTION_GET_METHODDESC(state->iptr, md);
387 paramslots = md->paramslots;
389 if ((stack - stackfloor) + 1 < paramslots) {
390 exceptions_throw_verifyerror(state->m,
391 "Trying to pop operand of an empty stack");
395 dv = stack - (paramslots - 1);
397 #define TYPECHECK_STACKBASED
399 #include <typecheck-invoke.inc>
401 #undef TYPECHECK_STACKBASED
406 static bool typecheck_stackbased_verify_builtin(verifier_state *state,
407 typedescriptor_t *stack,
408 typedescriptor_t *stackfloor)
411 typedescriptor_t *dv;
413 /* check stack depth */
415 /* XXX parse params */
417 paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
419 if ((stack - stackfloor) + 1 < paramslots) {
420 exceptions_throw_verifyerror(state->m,
421 "Trying to pop operand of an empty stack");
425 dv = stack - (paramslots - 1);
427 #define TYPECHECK_STACKBASED
429 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
430 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
431 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
432 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
433 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
434 #include <typecheck-builtins.inc>
436 #undef TYPECHECK_STACKBASED
440 throw_stack_type_error:
441 exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
445 static bool typecheck_stackbased_multianewarray(verifier_state *state,
446 typedescriptor_t *stack,
447 typedescriptor_t *stackfloor)
449 /* XXX recombine with verify_multianewarray */
451 classinfo *arrayclass;
452 arraydescriptor *desc;
454 typedescriptor_t *sp;
455 typedescriptor_t *dst;
457 /* destination slot */
459 i = state->iptr->s1.argcount;
463 /* check the array lengths on the stack */
465 if ((stack - stackfloor) + 1 < i) {
466 exceptions_throw_verifyerror(state->m,
467 "Trying to pop operand of an empty stack");
472 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
474 for (sp = dst; sp <= stack; ++sp) {
475 if (sp->type != TYPE_INT) {
476 exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
481 /* check array descriptor */
483 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
484 /* the array class reference has already been resolved */
485 arrayclass = state->iptr->sx.s23.s3.c.cls;
487 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
488 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
489 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
490 if (desc->dimension < state->iptr->s1.argcount)
491 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
493 /* set the array type of the result */
494 typeinfo_init_classinfo(&(dst->typeinfo), arrayclass);
498 constant_classref *cr;
500 /* the array class reference is still unresolved */
501 /* check that the reference indicates an array class of correct dimension */
502 cr = state->iptr->sx.s23.s3.c.ref;
507 /* { the dimension of the array class == i } */
509 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
510 if (i < state->iptr->s1.argcount)
511 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
513 /* set the array type of the result */
514 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
523 static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
526 typecheck_jsr_caller_t *jc;
528 for (jc = jsr->callers; jc; jc = jc->next)
529 if (jc->callblock == bptr)
532 jc = (typecheck_jsr_caller_t*) DumpMemory::allocate(sizeof(typecheck_jsr_caller_t));
533 jc->next = jsr->callers;
534 jc->callblock = bptr;
538 static typedescriptor_t *typecheck_stackbased_jsr(verifier_state *state,
539 typedescriptor_t *stack,
540 typedescriptor_t *stackfloor)
542 typecheck_jsr_t *jsr;
549 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
550 jsr = state->jsrinfos[tbptr->nr];
552 if (jsr && tbptr->flags == BBFINISHED) {
554 LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
556 exceptions_throw_verifyerror(state->m, "Recursive JSR");
560 assert(jsr->callers);
561 assert(jsr->callers->callblock);
563 /* copy the stack of the RET edge */
565 MCOPY(stackfloor, jsr->retstack, typedescriptor_t, jsr->retdepth);
566 stack = stackfloor + (jsr->retdepth - 1);
568 /* copy variables that were used in the subroutine from the RET edge */
570 for (i=0; i<state->numlocals; ++i)
571 if (jsr->usedlocals[i])
572 state->locals[i] = jsr->retlocals[i];
574 /* reach the following block */
576 if (!typecheck_stackbased_reach(state, state->bptr->next, stack,
577 (stack - stackfloor) + 1))
582 LOG1("first JSR to block L%03d", tbptr->nr);
584 jsr = (typecheck_jsr_t*) DumpMemory::allocate(sizeof(typecheck_jsr_t));
585 state->jsrinfos[tbptr->nr] = jsr;
587 jsr->blockflags = (char*) DumpMemory::allocate(sizeof(char) * state->basicblockcount);
588 jsr->retblock = NULL;
590 jsr->usedlocals = (char*) DumpMemory::allocate(sizeof(char) * state->numlocals);
591 MZERO(jsr->usedlocals, char, state->numlocals);
592 jsr->retlocals = (typedescriptor_t*) DumpMemory::allocate(sizeof(typedescriptor_t) * state->numlocals);
593 jsr->retstack = (typedescriptor_t*) DumpMemory::allocate(sizeof(typedescriptor_t) * state->m->maxstack);
597 LOG1("re-analysing JSR to block L%03d", tbptr->nr);
601 jsr->next = state->topjsr;
604 assert(state->iptr->sx.s23.s3.jsrtarget.block->flags == BBTYPECHECK_REACHED);
606 tbptr->flags = BBFINISHED;
608 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
609 jsr->blockflags[tbptr->nr] = tbptr->flags;
611 if (tbptr->flags == BBTYPECHECK_REACHED)
612 tbptr->flags = BBFINISHED;
615 state->iptr->sx.s23.s3.jsrtarget.block->flags = BBTYPECHECK_REACHED;
618 /* register this block as a caller, if not already done */
620 typecheck_stackbased_add_jsr_caller(jsr, state->bptr);
625 static bool typecheck_stackbased_ret(verifier_state *state,
626 typedescriptor_t *stack,
627 typedescriptor_t *stackfloor)
630 typecheck_jsr_caller_t *jsrcaller;
631 typecheck_jsr_t *jsr;
634 /* get the subroutine we are RETurning from */
636 tbptr = (basicblock*) TYPEINFO_RETURNADDRESS(state->locals[state->iptr->s1.varindex].typeinfo);
638 exceptions_throw_verifyerror(state->m, "Illegal RET");
642 LOG1("RET from subroutine L%03d", tbptr->nr);
643 jsr = state->jsrinfos[tbptr->nr];
646 /* check against recursion */
649 exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
653 /* check against multiple RETs for one subroutine */
655 if (jsr->retblock && jsr->retblock != state->bptr) {
656 exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
660 /* store data-flow of the RET edge */
662 jsr->retblock = state->bptr;
663 jsr->retdepth = (stack - stackfloor) + 1;
664 MCOPY(jsr->retstack, stackfloor, typedescriptor_t, jsr->retdepth);
665 MCOPY(jsr->retlocals, state->locals, typedescriptor_t, state->numlocals);
667 /* invalidate the returnAddress used by this RET */
668 /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
670 for (i=0; i<state->numlocals; ++i) {
671 typedescriptor_t *lc = &(jsr->retlocals[i]);
672 if (TYPE_IS_RETURNADDRESS(lc->type, lc->typeinfo))
673 if (TYPEINFO_RETURNADDRESS(lc->typeinfo) == tbptr) {
674 LOG1("invalidating returnAddress in local %d", i);
675 TYPEINFO_INIT_RETURNADDRESS(lc->typeinfo, NULL);
679 /* touch all callers of the subroutine, so they are analysed again */
681 for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
682 tbptr = jsrcaller->callblock;
683 LOG1("touching caller L%03d from RET", tbptr->nr);
684 assert(jsr->blockflags[tbptr->nr] >= BBFINISHED);
685 jsr->blockflags[tbptr->nr] = BBTYPECHECK_REACHED; /* XXX repeat? */
691 bool typecheck_stackbased(jitdata *jd)
693 register verifier_slot_t *stack;
694 verifier_slot_t *stackfloor;
699 verifier_slot_t temp;
700 branch_target_t *table;
701 lookup_target_t *lookup;
704 verifier_slot_t *dst;
705 verifier_state state;
708 typedescriptor_t exstack;
711 DOLOG( show_method(jd, SHOW_PARSE); );
713 /* initialize verifier state */
718 state.basicblocks = jd->basicblocks;
719 state.basicblockcount = jd->basicblockcount;
721 # define STATE (&state)
723 /* check that the basicblock numbers are valid */
726 jit_check_basicblock_numbers(jd);
729 /* check if this method is an instance initializer method */
731 state.initmethod = (state.m->name == utf_init);
733 /* allocate parameter descriptors if necessary */
735 descriptor_params_from_paramtypes(state.m->parseddesc, state.m->flags);
737 /* allocate the stack buffers */
739 stackfloor = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * (state.m->maxstack + 1));
740 state.stackceiling = stackfloor + state.m->maxstack;
741 stack = stackfloor - 1;
742 state.indepth = (s4*) DumpMemory::allocate(sizeof(s4) * state.basicblockcount);
743 state.startstack = (verifier_slot_t*) DumpMemory::allocate(sizeof(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 = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.numlocals);
753 state.startlocals = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.numlocals * state.basicblockcount);
755 /* allocate the buffer of active exception handlers */
757 state.handlers = (exception_entry**) DumpMemory::allocate(sizeof(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 = (typecheck_jsr_t**) DumpMemory::allocate(sizeof(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->clazz);
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_t *stack,
986 typedescriptor_t *stackfloor,
989 typedescriptor_t *sp;
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 #if defined(__cplusplus)
1016 #endif /* defined(ENABLE_VERIFIER) */
1020 * These are local overrides for various environment variables in Emacs.
1021 * Please do not remove this and leave it at the end of the file, where
1022 * Emacs will automagically detect them.
1023 * ---------------------------------------------------------------------
1026 * indent-tabs-mode: t
1030 * vim:noexpandtab:sw=4:ts=4: