* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / jit / verify / typecheck.c
index 877d1e8d88c0de1de7b7472f6f07306ee2d18720..5d21065fb217f3bfebe1e580b310c638c8ad20d1 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Edwin Steiner
 
    Changes: Christian Thalinger
 
-   $Id: typecheck.c 3577 2005-11-05 16:30:33Z twisti $
+   $Id: typecheck.c 4357 2006-01-22 23:33:38Z twisti $
 
 */
 
@@ -165,11 +165,11 @@ of the typeinfo of the stack slot.
 #include <assert.h>
 #include <string.h>
 
+#include "config.h"
 #include "vm/types.h"
+#include "vm/global.h"
 
-#include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
-
-#ifdef CACAO_TYPECHECK
+#ifdef ENABLE_VERIFIER
 
 #include "mm/memory.h"
 #include "toolbox/logging.h"
@@ -178,7 +178,6 @@ of the typeinfo of the stack slot.
 #include "vm/jit/patcher.h"
 #include "vm/loader.h"
 #include "vm/options.h"
-#include "vm/tables.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/stack.h"
 #include "vm/access.h"
@@ -364,7 +363,7 @@ void typecheck_print_statistics(FILE *file) {
        fprintf(file,"      (uninit.)    : %8d\n",stat_ins_field_uninitialized);
        fprintf(file,"    invocations    : %8d\n",stat_ins_invoke);
        fprintf(file,"      (unresolved) : %8d\n",stat_ins_invoke_unresolved);
-       fprintf(file,"    load primitive : %8d\n",stat_ins_primload);
+       fprintf(file,"    load primitive : (currently not counted) %8d\n",stat_ins_primload);
        fprintf(file,"    load address   : %8d\n",stat_ins_aload);
        fprintf(file,"    builtins       : %8d\n",stat_ins_builtin);
        fprintf(file,"        generic    : %8d\n",stat_ins_builtin_gen);
@@ -477,21 +476,12 @@ typedef struct verifier_state {
 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
             TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
 
-#define TYPESTACK_IS_REFERENCE(sptr) \
-            TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
-
 #define TYPESTACK_RETURNADDRESSSET(sptr) \
             ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
 
 #define RETURNADDRESSSET_SEEK(set,pos) \
             do {int i; for (i=pos;i--;) set=set->alt;} while(0)
 
-#define TYPESTACK_COPY(sp,copy)                                                                        \
-               do {for(; sp; sp=sp->prev, copy=copy->prev) {           \
-                                       copy->type = sp->type;                                          \
-                                       TYPEINFO_COPY(sp->typeinfo,copy->typeinfo);     \
-                               }} while (0)                                                                    \
-
 /* typestack_copy **************************************************************
  
    Copy the types on the given stack to the destination stack.
@@ -524,6 +514,7 @@ typestack_copy(verifier_state *state,stackptr dst,stackptr y,typevector *selecte
        int k;
        
        for (;dst; dst=dst->prev, y=y->prev) {
+               /* XXX only check the following two in debug mode? */
                if (!y) {
                        *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
                        return false;
@@ -712,7 +703,30 @@ typestack_add(stackptr dst,stackptr y,int ky)
        }
 }
 
-/* 'a' and 'b' are assumed to have passed typestack_canmerge! */
+/* typestack_separable_with ****************************************************
+   This function answers the question: If variant 'kb' of typestack 'b' is
+   added to typestack 'a', will the result be separable?
+
+   A typestack is called 'separable' if it has at least one slot of type
+   returnAddress that contains at least two different return addresses.
+   (ie. a RET using the value in this slot could go to more than one target)
+   
+   IN:
+          a................the first typestack
+          b................the second typestack
+          kb...............the k-index of the variant that should be selected
+                           from typestack 'b'
+
+   OUT:
+       true.............the result would be separable
+          false............the result would not be separable
+
+   PRE-CONDITION:
+       'a' and 'b' are assumed to have passed typestack_canmerge!
+
+*******************************************************************************/
+
 static bool
 typestack_separable_with(stackptr a,stackptr b,int kb)
 {
@@ -735,7 +749,33 @@ typestack_separable_with(stackptr a,stackptr b,int kb)
        return false;
 }
 
-/* 'a' and 'b' are assumed to have passed typestack_canmerge! */
+/* typestack_separable_from ****************************************************
+   This function answers the question: Is variant 'ka' of typestack 'a'
+   separable from variant 'kb' of typestack 'b'?
+
+   Two variants of typestacks are called 'separable' from each other, if there
+   is at least one slot for which the variants contain different return addresses.
+   (ie. a RET using the value in this slot would go to one target in the first
+   variant and to another target in the second variant)
+   
+   IN:
+          a................the first typestack
+          ka...............the k-index of the variant that should be selected
+                           from typestack 'a'
+          b................the second typestack
+          kb...............the k-index of the variant that should be selected
+                           from typestack 'b'
+
+   OUT:
+       true.............the variants are separable
+          false............the variants are not separable
+
+   PRE-CONDITION:
+       'a' and 'b' are assumed to have passed typestack_canmerge!
+
+*******************************************************************************/
+
 static bool
 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
 {
@@ -955,7 +995,7 @@ typestate_reach(verifier_state *state,
                
                if (!typestack_copy(state,destblock->instack,ystack,yloc))
                        return false;
-               COPY_TYPEVECTORSET(yloc,destloc,state->numlocals);
+               typevectorset_copy_inplace(yloc,destloc,state->numlocals);
                changed = true;
        }
        else {
@@ -1023,62 +1063,76 @@ typestate_ret(verifier_state *state,int retindex)
        return true;
 }
 
-/****************************************************************************/
-/* MACROS FOR LOCAL VARIABLE CHECKING                                       */
-/****************************************************************************/
+/* typestate_save_instack ******************************************************
+   Save the input stack of the current basic block in the "savedstackbuf"
+   of the verifier state.
 
-#define INDEX_ONEWORD(num)                                                                             \
-       do { if((num)<0 || (num)>=state->validlocals)                           \
-                       TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
-#define INDEX_TWOWORD(num)                                                                             \
-       do { if((num)<0 || ((num)+1)>=state->validlocals)                       \
-                       TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
+   This function must be called before an instruction modifies a stack slot
+   that happens to be part of the instack of the current block. In such
+   cases the instack of the block must be saved, and restored at the end
+   of the analysis of this basic block, so that the instack again reflects
+   the *input* to this basic block (and does not randomly contain types
+   that appear within the block).
 
-#define STORE_ONEWORD(num,type)                                                                        \
-       do {typevectorset_store(state->localset,num,type,NULL);} while(0)
+   IN:
+       state............current state of the verifier
 
-#define STORE_TWOWORD(num,type)                                                                                \
-       do {typevectorset_store_twoword(state->localset,num,type);} while(0)
+*******************************************************************************/
 
+static void
+typestate_save_instack(verifier_state *state)
+{
+       stackptr sp;
+       stackptr dest;
+       s4 i;
+       
+       LOG("saving input stack types");
+       if (!state->savedstackbuf) {
+               LOG("allocating savedstack buffer");
+               state->savedstackbuf = DMNEW(stackelement, state->cd->maxstack);
+               state->savedstackbuf->prev = NULL;
+               for (i = 1; i < state->cd->maxstack; ++i)
+                       state->savedstackbuf[i].prev = state->savedstackbuf+(i-1);
+       }
+       sp = state->savedstack = state->bptr->instack;
+       dest = state->bptr->instack = state->savedstackbuf + (state->bptr->indepth-1);
+       
+       for(; sp; sp=sp->prev, dest=dest->prev) {
+               dest->type = sp->type;
+               TYPEINFO_COPY(sp->typeinfo,dest->typeinfo);
+       }
+}
 
-#ifdef TYPECHECK_VERBOSE
-#define WORDCHECKFAULT \
-       do { \
-               dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n", \
-               state->iptr->op1,state->iptr->method->class->name->text, \
-                       state->iptr->method->name->text,state->m->class->name->text,state->m->name->text); \
-               show_icmd(state->iptr++, false); \
-               show_icmd(state->iptr, false); \
-       } while (0)
-#else
-#define WORDCHECKFAULT
-#endif
+/* typestate_restore_instack ***************************************************
+   Restore the input stack of the current basic block that has been previously
+   saved by `typestate_save_instack`.
 
+   IN:
+       state............current state of the verifier
 
-#define CHECK_ONEWORD(num,tp)                                                                                  \
-       do {TYPECHECK_COUNT(stat_ins_primload);                                                         \
-               if (state->jsrencountered) {                                                                                    \
-                       if (!typevectorset_checktype(state->localset,num,tp)) {                         \
-                               WORDCHECKFAULT; \
-                               TYPECHECK_VERIFYERROR_bool("Variable type mismatch");                                           \
-                       }       \
-               }                                                                                                                               \
-               else {                                                                                                                  \
-                       if (state->localset->td[num].type != tp) {                                                      \
-                               TYPECHECK_VERIFYERROR_bool("Variable type mismatch");                                           \
-                               WORDCHECKFAULT; \
-                       } \
-               }                                                                                                                               \
-               } while(0)
-
-#define CHECK_TWOWORD(num,type)                                                                                        \
-       do {TYPECHECK_COUNT(stat_ins_primload);                                                         \
-               if (!typevectorset_checktype(state->localset,num,type)) {                \
-                       WORDCHECKFAULT; \
-                       TYPECHECK_VERIFYERROR_bool("Variable type mismatch");                           \
-               } \
-       } while(0)
+*******************************************************************************/
 
+static void
+typestate_restore_instack(verifier_state *state)
+{
+       stackptr sp;
+       stackptr dest;
+       
+       TYPECHECK_COUNT(stat_savedstack);
+       LOG("restoring saved instack");
+
+       sp = state->bptr->instack;
+       dest = state->savedstack;
+       for(; sp; sp=sp->prev, dest=dest->prev) {
+               dest->type = sp->type;
+               TYPEINFO_COPY(sp->typeinfo,dest->typeinfo);
+       }
+
+       state->bptr->instack = state->savedstack;
+       state->savedstack = NULL;
+}
 
 /****************************************************************************/
 /* MISC MACROS                                                              */
@@ -1090,21 +1144,6 @@ typestate_ret(verifier_state *state,int retindex)
 
 #define ISBUILTIN(v)   (bte->fp == (functionptr) (v))
 
-/* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
- * Input:
- *     class........class of the current method
- *     state........verifier state
- */
-#define TYPECHECK_LEAVE                                                 \
-    do {                                                                \
-        if (state->initmethod && state->m->class != class_java_lang_Object) {         \
-            /* check the marker variable */                             \
-            LOG("Checking <init> marker");                              \
-            if (!typevectorset_checktype(state->localset,state->numlocals-1,TYPE_INT))\
-                TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'");      \
-        }                                                               \
-    } while (0)
-
 /* verify_invocation ***********************************************************
  
    Verify an ICMD_INVOKE* instruction.
@@ -1180,7 +1219,7 @@ verify_invocation(verifier_state *state)
                                LOGINFO(&(stack->typeinfo));
                                ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo);
                                if (ins)
-                                       initclass = CLASSREF_OR_CLASSINFO(ins[-1].val.a);
+                                       initclass = CLASSREF_OR_CLASSINFO(ins[-1].target);
                                else
                                        initclass.cls = state->m->class;
                                LOGSTR("class: "); LOGNAME(initclass); LOGNL;
@@ -1224,21 +1263,7 @@ verify_invocation(verifier_state *state)
                                 * we are going to replace.
                                 */
                                if (stack <= state->bptr->instack && !state->savedstack)
-                               {
-                                       stackptr sp;
-                                       stackptr copy;
-                                       LOG("saving input stack types");
-                                       if (!state->savedstackbuf) {
-                                               LOG("allocating savedstack buffer");
-                                               state->savedstackbuf = DMNEW(stackelement, state->cd->maxstack);
-                                               state->savedstackbuf->prev = NULL;
-                                               for (i = 1; i < state->cd->maxstack; ++i)
-                                                       state->savedstackbuf[i].prev = state->savedstackbuf+(i-1);
-                                       }
-                                       sp = state->savedstack = state->bptr->instack;
-                                       copy = state->bptr->instack = state->savedstackbuf + (state->bptr->indepth-1);
-                                       TYPESTACK_COPY(sp,copy);
-                               }
+                                       typestate_save_instack(state);
 
                                if (!typeinfo_init_class(&(stack->typeinfo),initclass))
                                        return false;
@@ -1380,19 +1405,10 @@ verify_builtin(verifier_state *state)
        /* XXX this is an ugly if-chain but twisti did not want a function */
        /* pointer in builtintable_entry for this, so here you go.. ;)     */
 
-       if (ISBUILTIN(BUILTIN_new) || ISBUILTIN(PATCHER_builtin_new)) {
+       if (ISBUILTIN(BUILTIN_new)) {
                if (state->iptr[-1].opc != ICMD_ACONST)
                        TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without class");
-               cls.any = state->iptr[-1].val.a;
-               if (cls.any && !IS_CLASSREF(cls)) {
-                       /* The following check also forbids array classes and interfaces: */
-                       if ((cls.cls->flags & ACC_ABSTRACT) != 0)
-                               TYPECHECK_VERIFYERROR_bool("Invalid instruction: NEW creating instance of abstract class");
-               }
-               else {
-                       /* in this case, the patcher will perform the non-abstract check */
-                       TYPECHECK_ASSERT(ISBUILTIN(PATCHER_builtin_new));
-               }
+               cls.any = state->iptr[-1].target;
                TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,state->iptr);
        }
        else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
@@ -1429,46 +1445,18 @@ verify_builtin(verifier_state *state)
        }
        else if (ISBUILTIN(BUILTIN_newarray))
        {
-               classinfo *c;
                TYPECHECK_INT(state->curstack->prev);
-               if (state->iptr[-1].opc != ICMD_ACONST)
-                       TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
-               c = (classinfo *) state->iptr[-1].val.a;
-               if (!c)
-                       TYPECHECK_VERIFYERROR_bool("ANEWARRAY with unlinked class");
-               if (!c->vftbl->arraydesc)
-                       TYPECHECK_VERIFYERROR_bool("ANEWARRAY with non-array class");
-               TYPEINFO_INIT_CLASSINFO(dst->typeinfo, c);
-       }
-       else if (ISBUILTIN(PATCHER_builtin_newarray))
-       {
-               TYPECHECK_INT(state->curstack->prev);
-               if (state->iptr[-1].opc != ICMD_ACONST)
-                       TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
-               if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[-1].val.a)))
-                       return false;
+               if (state->iptr[-1].opc != ICMD_ACONST || !state->iptr[-1].target)
+                       TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without class");
+               /* XXX check that it is an array class(ref) */
+               typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[-1].target));
        }
        else if (ISBUILTIN(BUILTIN_arrayinstanceof))
        {
-               classinfo *c;
-               TYPECHECK_ADR(state->curstack->prev);
-               if (state->iptr[-1].opc != ICMD_ACONST)
-                       TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without classinfo");
-               c = (classinfo *) state->iptr[-1].val.a;
-               if (!c)
-                       TYPECHECK_VERIFYERROR_bool("INSTANCEOF with unlinked class");
-               if (!c->vftbl->arraydesc)
-                       TYPECHECK_VERIFYERROR_bool("internal error: builtin_arrayinstanceof with non-array class");
-       }
-       else if (ISBUILTIN(PATCHER_builtin_arrayinstanceof)) {
-               constant_classref *cr;
-               
                TYPECHECK_ADR(state->curstack->prev);
                if (state->iptr[-1].opc != ICMD_ACONST)
                        TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
-               cr = (constant_classref *) state->iptr[-1].val.a;
-               if (cr->name->text[0] != '[')
-                       TYPECHECK_VERIFYERROR_bool("internal error: builtin_arrayinstanceof with non-array class refernce");
+               /* XXX check that it is an array class(ref) */
        }
        else {
                return verify_generic_builtin(state);
@@ -1511,7 +1499,7 @@ verify_multianewarray(verifier_state *state)
        }
 
        /* check array descriptor */
-       if (state->iptr[0].target == NULL) {
+       if (state->iptr[0].val.a != NULL) {
                /* the array class reference has already been resolved */
                arrayclass = (classinfo *) state->iptr[0].val.a;
                if (!arrayclass)
@@ -1522,7 +1510,7 @@ verify_multianewarray(verifier_state *state)
                        TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
 
                /* set the array type of the result */
-               TYPEINFO_INIT_CLASSINFO(state->iptr->dst->typeinfo, arrayclass);
+               typeinfo_init_classinfo(&(state->iptr->dst->typeinfo), arrayclass);
        }
        else {
                const char *p;
@@ -1530,7 +1518,7 @@ verify_multianewarray(verifier_state *state)
                
                /* the array class reference is still unresolved */
                /* check that the reference indicates an array class of correct dimension */
-               cr = (constant_classref *) state->iptr[0].val.a;
+               cr = (constant_classref *) state->iptr[0].target;
                i = 0;
                p = cr->name->text;
                while (p[i] == '[')
@@ -1542,7 +1530,7 @@ verify_multianewarray(verifier_state *state)
                        TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
 
                /* set the array type of the result */
-               if (!typeinfo_init_class(&(state->iptr->dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].val.a)))
+               if (!typeinfo_init_class(&(state->iptr->dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
                        return false;
        }
 
@@ -1608,7 +1596,7 @@ verify_basic_block(verifier_state *state)
        state->handlers[len] = NULL;
 
        /* init variable types at the start of this block */
-       COPY_TYPEVECTORSET(MGET_TYPEVECTOR(state->localbuf,b_index,state->numlocals),
+       typevectorset_copy_inplace(MGET_TYPEVECTOR(state->localbuf,b_index,state->numlocals),
                        state->localset,state->numlocals);
 
        /* XXX FIXME FOR INLINING */
@@ -1625,7 +1613,7 @@ verify_basic_block(verifier_state *state)
                                        /* of eclipse 3.0.2                                                  */
                                        if (TYPEINFO_NEWOBJECT_INSTRUCTION(state->localset->td[i].info) != NULL) {
                                                /*show_icmd_method(state->m, state->cd, state->rd);*/
-                                               printf("Uninitialized variale: %d, block: %d\n", i, state->bptr->debug_nr);
+                                               printf("Uninitialized variable: %d, block: %d\n", i, state->bptr->debug_nr);
                                                TYPECHECK_VERIFYERROR_bool("Uninitialized object in local variable inside try block");
                                        }
                                }
@@ -1717,16 +1705,26 @@ verify_basic_block(verifier_state *state)
                                /****************************************/
                                /* PRIMITIVE VARIABLE ACCESS            */
 
-                       case ICMD_ILOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
-                       case ICMD_FLOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
-                       case ICMD_IINC:  CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
-                       case ICMD_LLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_LONG); break;
-                       case ICMD_DLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
-
-                       case ICMD_FSTORE: STORE_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
-                       case ICMD_ISTORE: STORE_ONEWORD(state->iptr->op1,TYPE_INT); break;
-                       case ICMD_LSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_LONG); break;
-                       case ICMD_DSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
+                       case ICMD_ILOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_INT)) 
+                                                                TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        break;
+                       case ICMD_IINC:  if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_INT))
+                                                                TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        break;
+                       case ICMD_FLOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_FLOAT))
+                                                                TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        break;
+                       case ICMD_LLOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_LONG))
+                                                                TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        break;
+                       case ICMD_DLOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_DOUBLE))
+                                                                TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        break;
+
+                       case ICMD_ISTORE: typevectorset_store(state->localset,state->iptr->op1,TYPE_INT,NULL); break;
+                       case ICMD_FSTORE: typevectorset_store(state->localset,state->iptr->op1,TYPE_FLOAT,NULL); break;
+                       case ICMD_LSTORE: typevectorset_store_twoword(state->localset,state->iptr->op1,TYPE_LONG); break;
+                       case ICMD_DSTORE: typevectorset_store_twoword(state->localset,state->iptr->op1,TYPE_DOUBLE); break;
 
                                /****************************************/
                                /* LOADING ADDRESS FROM VARIABLE        */
@@ -1822,11 +1820,6 @@ fieldaccess_tail:
                                if (!resolve_field(uf,resolveLazy,fieldinfop))
                                        return false;
 
-                               /* we need a patcher, so this is not a leafmethod */
-#if defined(__MIPS__)
-                               if (!*fieldinfop || !(*fieldinfop)->class->initialized)
-                                       state->cd->method->isleafmethod = false;
-#endif
                                TYPECHECK_COUNTIF(!*fieldinfop,stat_ins_field_unresolved);
                                TYPECHECK_COUNTIF(*fieldinfop && !(*fieldinfop)->class->initialized,stat_ins_field_uninitialized);
                                        
@@ -1965,11 +1958,18 @@ fieldaccess_tail:
                                /* ADDRESS CONSTANTS                    */
 
                        case ICMD_ACONST:
-                               if (state->iptr->val.a == NULL)
-                                       TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
-                               else
-                                       /* string constant (or constant for builtin function) */
-                                       TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
+                               if (state->iptr->target) {
+                                       /* a java.lang.Class reference */
+                                       TYPEINFO_INIT_JAVA_LANG_CLASS(dst->typeinfo,(constant_classref *)state->iptr->target);
+                               }
+                               else {
+                                       if (state->iptr->val.a == NULL)
+                                               TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
+                                       else {
+                                               /* string constant (or constant for builtin function) */
+                                               typeinfo_init_classinfo(&(dst->typeinfo),class_java_lang_String);
+                                       }
+                               }
                                break;
 
                                /****************************************/
@@ -1983,32 +1983,13 @@ fieldaccess_tail:
 
                                cls = (classinfo *) state->iptr[0].val.a;
                                if (cls)
-                                       TYPEINFO_INIT_CLASSINFO(dst->typeinfo,cls);
+                                       typeinfo_init_classinfo(&(dst->typeinfo),cls);
                                else
                                        if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
                                                return false;
                                maythrow = true;
                                break;
 
-                       case ICMD_ARRAYCHECKCAST:
-                               TYPECHECK_ADR(state->curstack);
-                               /* returnAddress is not allowed */
-                               if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
-                                       TYPECHECK_VERIFYERROR_bool("Illegal instruction: ARRAYCHECKCAST on non-reference");
-
-                               if (state->iptr[0].op1) {
-                                       /* a resolved array class */
-                                       cls = (classinfo *) state->iptr[0].target;
-                                       TYPEINFO_INIT_CLASSINFO(dst->typeinfo, cls);
-                               }
-                               else {
-                                       /* an unresolved array class reference */
-                                       if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
-                                               return false;
-                               }
-                               maythrow = true;
-                               break;
-
                        case ICMD_INSTANCEOF:
                                TYPECHECK_ADR(state->curstack);
                                /* returnAddress is not allowed */
@@ -2160,7 +2141,14 @@ switch_instruction_tail:
                                if (state->returntype.type != TYPE_VOID) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
 return_tail:
                                TYPECHECK_COUNT(stat_ins_primitive_return);
-                               TYPECHECK_LEAVE;
+
+                               if (state->initmethod && state->m->class != class_java_lang_Object) {
+                                       /* Check if the 'this' instance has been initialized. */
+                                       LOG("Checking <init> marker");
+                                       if (!typevectorset_checktype(state->localset,state->numlocals-1,TYPE_INT))
+                                               TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'");
+                               }
+
                                superblockend = true;
                                maythrow = true;
                                break;
@@ -2271,7 +2259,9 @@ return_tail:
                                 * Instructions below...
                                 *     *) don't operate on local variables,
                                 *     *) don't operate on references,
-                                *     *) don't operate on returnAddresses.
+                                *     *) don't operate on returnAddresses,
+                                *     *) don't affect control flow (except
+                                *        by throwing exceptions).
                                 *
                                 * (These instructions are typechecked in
                                 *  analyse_stack.)
@@ -2326,10 +2316,6 @@ return_tail:
                        case ICMD_LSHL:
                        case ICMD_LSHR:
                        case ICMD_LUSHR:
-#if 0
-                       case ICMD_IREM0X10001:
-                       case ICMD_LREM0X10001:
-#endif
                        case ICMD_IMULPOW2:
                        case ICMD_LMULPOW2:
                        case ICMD_IDIVPOW2:
@@ -2457,15 +2443,9 @@ return_tail:
         * have been saved if an <init> call inside the block has
         * modified the instack types. (see INVOKESPECIAL) */
 
-       if (state->savedstack) {
-               stackptr sp = state->bptr->instack;
-               stackptr copy = state->savedstack;
-               TYPECHECK_COUNT(stat_savedstack);
-               LOG("restoring saved instack");
-               TYPESTACK_COPY(sp,copy);
-               state->bptr->instack = state->savedstack;
-               state->savedstack = NULL;
-       }
+       if (state->savedstack)
+               typestate_restore_instack(state);
+
        return true;
 }
 
@@ -2513,7 +2493,7 @@ verify_init_locals(verifier_state *state)
         if (state->initmethod)
             TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
         else
-            TYPEINFO_INIT_CLASSINFO(td->info, state->m->class);
+            typeinfo_init_classinfo(&(td->info), state->m->class);
         td++;
                i--;
     }
@@ -2725,7 +2705,7 @@ methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
        
        state.excstack.prev = NULL;
        state.excstack.type = TYPE_ADR;
-       TYPEINFO_INIT_CLASSINFO(state.excstack.typeinfo,
+       typeinfo_init_classinfo(&(state.excstack.typeinfo),
                                                        class_java_lang_Throwable); /* changed later */
 
     LOG("Exception handler stacks set.\n");
@@ -2773,7 +2753,7 @@ methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
        return state.m;
 }
 
-#endif /* CACAO_TYPECHECK */
+#endif /* ENABLE_VERIFIER */
 
 /*
  * These are local overrides for various environment variables in Emacs.