1 /* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
3 Copyright (C) 1996-2005, 2006, 2007, 2008
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 if (!state.m->parseddesc->params)
736 if (!descriptor_params_from_paramtypes(state.m->parseddesc,state.m->flags))
739 /* allocate the stack buffers */
741 stackfloor = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * (state.m->maxstack + 1));
742 state.stackceiling = stackfloor + state.m->maxstack;
743 stack = stackfloor - 1;
744 state.indepth = (s4*) DumpMemory::allocate(sizeof(s4) * state.basicblockcount);
745 state.startstack = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.m->maxstack * state.basicblockcount);
747 /* allocate the local variables buffers */
749 state.numlocals = state.m->maxlocals;
750 state.validlocals = state.m->maxlocals;
751 if (state.initmethod)
752 state.numlocals++; /* extra marker variable */
754 state.locals = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.numlocals);
755 state.startlocals = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.numlocals * state.basicblockcount);
757 /* allocate the buffer of active exception handlers */
759 state.handlers = (exception_entry**) DumpMemory::allocate(sizeof(exception_entry*) * (state.jd->exceptiontablelength + 1));
761 /* initialize instack of exception handlers */
763 exstack.type = TYPE_ADR;
764 typeinfo_init_classinfo(&(exstack.typeinfo),
765 class_java_lang_Throwable); /* changed later */
767 LOG("Exception handler stacks set.\n");
769 /* initialize jsr info buffer */
771 state.jsrinfos = (typecheck_jsr_t**) DumpMemory::allocate(sizeof(typecheck_jsr_t*) * state.basicblockcount);
772 MZERO(state.jsrinfos, typecheck_jsr_t *, state.basicblockcount);
774 /* initialize stack of first block */
776 state.indepth[0] = 0;
778 /* initialize locals of first block */
780 /* if this is an instance method initialize the "this" ref type */
782 if (!(state.m->flags & ACC_STATIC)) {
783 if (state.validlocals < 1)
784 VERIFY_ERROR("Not enough local variables for method arguments");
785 dst = state.startlocals;
786 dst->type = TYPE_ADR;
787 if (state.initmethod)
788 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo, NULL);
790 typeinfo_init_classinfo(&(dst->typeinfo), state.m->clazz);
795 LOG("'this' argument set.\n");
797 len = typedescriptors_init_from_methoddesc(state.startlocals + skip,
799 state.validlocals, true, skip, &state.returntype);
803 /* set remaining locals to void */
805 for (i = skip + len; i<state.numlocals; ++i)
806 state.startlocals[i].type = TYPE_VOID;
808 /* initialize block flags */
810 typecheck_init_flags(&state, BBUNDEF);
812 /* iterate until fixpoint reached */
816 state.repeat = false;
818 /* iterate over the basic blocks */
820 for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
822 if (state.bptr->flags != BBTYPECHECK_REACHED)
825 DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
827 /* mark this block as analysed */
829 state.bptr->flags = BBFINISHED;
831 /* determine the active exception handlers for this block */
832 /* XXX could use a faster algorithm with sorted lists or */
834 /* XXX reuse code from variables based verifer? */
836 for (ex = STATE->jd->exceptiontable; ex ; ex = ex->down) {
837 if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
838 LOG1("\tactive handler L%03d", ex->handler->nr);
839 STATE->handlers[len++] = ex;
842 STATE->handlers[len] = NULL;
844 /* initialize the locals */
847 state.startlocals + (state.bptr->nr * state.numlocals),
848 verifier_slot_t, state.numlocals);
850 /* initialize the stack */
852 len = state.indepth[state.bptr->nr];
855 state.startstack + (state.bptr->nr * state.m->maxstack),
856 verifier_slot_t, len);
858 stack = stackfloor + (len - 1);
860 /* iterate over the instructions in this block */
862 state.iptr = state.bptr->iinstr;
863 len = state.bptr->icount;
865 superblockend = false;
867 for (; len--; state.iptr++) {
872 DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
874 switch (state.iptr->opc) {
875 #define TYPECHECK_STACKBASED 1
876 #define STATE (&state)
877 #define IPTR state.iptr
878 #define BPTR state.bptr
879 #define METHOD state.m
880 #define LOCAL_SLOT(index) (state.locals + (index))
883 LOG("EXCEPTION THROWN!\n"); \
887 #include <typecheck-stackbased-gen.inc>
888 #undef TYPECHECK_STACKBASED
891 /* reach exception handlers for this instruction */
894 TYPECHECK_COUNT(stat_ins_maythrow);
895 TYPECHECK_MARK(STATE->stat_maythrow);
896 LOG("\treaching exception handlers");
898 while (STATE->handlers[i]) {
899 TYPECHECK_COUNT(stat_handlers_reached);
900 if (STATE->handlers[i]->catchtype.any)
901 exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
903 exstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
904 if (!typecheck_stackbased_reach(
906 STATE->handlers[i]->handler,
914 /* propagate types to the following block */
916 if (!superblockend) {
917 if (!typecheck_stackbased_reach(&state, state.bptr->next,
918 stack, stack - stackfloor + 1))
921 } /* end loop over blocks */
923 while (!state.repeat && state.topjsr) {
924 LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
926 /* propagate down used locals */
928 if (state.topjsr->next) {
929 for (i=0; i<state.numlocals; ++i)
930 state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
933 /* restore REACHED flags */
935 for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
936 assert(tbptr->flags != BBTYPECHECK_REACHED);
937 if (state.topjsr->blockflags[tbptr->nr] == BBTYPECHECK_REACHED) {
938 tbptr->flags = BBTYPECHECK_REACHED;
943 /* dactivate the subroutine */
945 state.topjsr->active = false;
946 state.topjsr = state.topjsr->next;
948 } while (state.repeat);
950 /* reset block flags */
952 typecheck_reset_flags(&state);
954 LOG("typecheck_stackbased successful");
958 throw_stack_underflow:
959 LOG("STACK UNDERFLOW!");
960 exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
963 throw_stack_overflow:
964 LOG("STACK OVERFLOW!");
965 exceptions_throw_verifyerror(state.m, "Stack size too large");
968 throw_stack_type_error:
969 LOG("STACK TYPE ERROR!");
970 exceptions_throw_verifyerror(state.m, "Mismatched stack types");
973 throw_local_type_error:
974 LOG("LOCAL TYPE ERROR!");
975 exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
978 throw_stack_category_error:
979 LOG("STACK CATEGORY ERROR!");
980 exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
985 #if defined(TYPECHECK_VERBOSE)
986 static void typecheck_stackbased_show_state(verifier_state *state,
987 typedescriptor_t *stack,
988 typedescriptor_t *stackfloor,
991 typedescriptor_t *sp;
994 LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
995 for (sp=stackfloor; sp <= stack; sp++) {
997 DOLOG( typedescriptor_print(stdout, sp); );
999 LOGSTR(" ] locals [");
1000 for (i=0; i<state->numlocals; ++i) {
1002 DOLOG( typedescriptor_print(stdout, state->locals + i); );
1006 if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
1008 DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
1014 #if defined(__cplusplus)
1018 #endif /* defined(ENABLE_VERIFIER) */
1022 * These are local overrides for various environment variables in Emacs.
1023 * Please do not remove this and leave it at the end of the file, where
1024 * Emacs will automagically detect them.
1025 * ---------------------------------------------------------------------
1028 * indent-tabs-mode: t
1032 * vim:noexpandtab:sw=4:ts=4: