* src/vm/resolve.c (resolve_method_verifier_checks): Factored out
[cacao.git] / src / vm / jit / verify / typecheck.c
index 3fb13d19bef7dce0d93084a5fc0e80dc1c667283..399f4970ff76f6619c3a3b463c23970ca6d12425 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 3645 2005-11-09 19:33:45Z edwin $
+   $Id: typecheck.c 5725 2006-10-09 22:19:22Z edwin $
 
 */
 
@@ -101,19 +101,6 @@ checks for protected members.)
        checked. (See the constrain_unresolved_... and the resolve_...
        methods.)[3]
 
-*) The boundaries of jsr subroutines are not well-defined. For a given
-instruction it may be impossible to tell whether it is part of a
-subroutine, or to which subroutine it belongs.
-
-       Solution: The typechecker implements a method developed by
-       Alessandro Coglio[4] which treats each returnAddress as a distinct
-       type that is not merged with other returnAddresses. This way, when a
-       RET instruction is reached, we know exactly which types to propagate
-       to which return target among the possible targets of the RET. The
-       downside of this method is, that for each slot/variable we must
-       store not just one type, but one type *for each possible use of the
-       returnAddresses* that currently are in a slot/variable.[5]
-
 *) Checks for uninitialized object instances are hard because after the
 invocation of <init> on an uninitialized object *all* slots/variables
 referring to this object (and exactly those slots/variables) must be
@@ -122,6 +109,9 @@ marked as initialized.
        Solution: The JVM spec describes a solution, which has been
        implemented in this typechecker.
 
+Note that some checks mentioned in the JVM spec are unnecessary[4] and
+not performed by either the reference implementation, or this implementation.
+
 
 --- Footnotes
 
@@ -144,32 +134,21 @@ after loading, while our constraints are checked when the field/method
 is accessed for the first time, so we can guarantee lexically correct
 error reporting.
 
-[4] Alessandro Coglio, Simple Verification Technique for Complex Java
-Bytecode Subroutines, 4th ECOOP Workshop on Formal Techniques for
-Java-like Programs, June 2002
-http://www.kestrel.edu/home/people/coglio/ftjp02.pdf
-
-[5] This is a major source of code complexity. The main data structures
-dealing with this are the "typevector set" and the typestack. The
-"typevector set" is a set of alternative typevectors, such that each
-typevector specifies the types of the local variables for a single
-combination of returnAddresses used. Thus we support full polymorphism
-of subroutines over the types of local variables. The typestack,
-however, does not support polymorphism, both for historical and JVM-spec
-reasons. A slot of the typestack may, however, contain multiple
-alternative returnAddresses, which is realized by a linked list hanging
-of the typeinfo of the stack slot.
-
+[4] Alessandro Coglio
+    Improving the official specification of Java bytecode verification
+    Proceedings of the 3rd ECOOP Workshop on Formal Techniques for Java Programs
+    June 2001
+    citeseer.ist.psu.edu/article/coglio03improving.html
 */
 
 #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,12 +157,11 @@ 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/jit/show.h"
 #include "vm/access.h"
 #include "vm/resolve.h"
-
+#include "vm/exceptions.h"
 
 /****************************************************************************/
 /* DEBUG HELPERS                                                            */
@@ -196,33 +174,33 @@ of the typeinfo of the stack slot.
 #endif
 
 #ifdef TYPECHECK_VERBOSE_OPT
-bool typecheckverbose = false;
-#define DOLOG(action)  do { if (typecheckverbose) {action;} } while(0)
+bool opt_typecheckverbose = false;
+#define DOLOG(action)  do { if (opt_typecheckverbose) {action;} } while(0)
 #else
 #define DOLOG(action)
 #endif
 
 #ifdef TYPECHECK_VERBOSE
 #define TYPECHECK_VERBOSE_IMPORTANT
-#define LOG(str)           DOLOG(log_text(str))
-#define LOG1(str,a)        DOLOG(dolog(str,a))
-#define LOG2(str,a,b)      DOLOG(dolog(str,a,b))
-#define LOG3(str,a,b,c)    DOLOG(dolog(str,a,b,c))
-#define LOGIF(cond,str)    DOLOG(do {if (cond) log_text(str);} while(0))
+#define LOGNL              DOLOG(puts(""))
+#define LOG(str)           DOLOG(puts(str);)
+#define LOG1(str,a)        DOLOG(printf(str,a); LOGNL)
+#define LOG2(str,a,b)      DOLOG(printf(str,a,b); LOGNL)
+#define LOG3(str,a,b,c)    DOLOG(printf(str,a,b,c); LOGNL)
+#define LOGIF(cond,str)    DOLOG(do {if (cond) { puts(str); }} while(0))
 #ifdef  TYPEINFO_DEBUG
-#define LOGINFO(info)      DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
+#define LOGINFO(info)      DOLOG(do {typeinfo_print_short(stdout,(info)); LOGNL;} while(0))
 #else
 #define LOGINFO(info)
-#define typevectorset_print(x,y,z)
+#define typevector_print(x,y,z)
 #endif
-#define LOGFLUSH           DOLOG(fflush(get_logfile()))
-#define LOGNL              DOLOG(log_plain("\n"))
-#define LOGSTR(str)        DOLOG(log_plain(str))
-#define LOGSTR1(str,a)     DOLOG(dolog_plain(str,a))
-#define LOGSTR2(str,a,b)   DOLOG(dolog_plain(str,a,b))
-#define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
-#define LOGSTRu(utf)       DOLOG(log_plain_utf(utf))
-#define LOGNAME(c)         DOLOG(do {log_plain_utf(IS_CLASSREF(c) ? c.ref->name : c.cls->name);} while(0))
+#define LOGFLUSH           DOLOG(fflush(stdout))
+#define LOGSTR(str)        DOLOG(printf("%s", str))
+#define LOGSTR1(str,a)     DOLOG(printf(str,a))
+#define LOGSTR2(str,a,b)   DOLOG(printf(str,a,b))
+#define LOGSTR3(str,a,b,c) DOLOG(printf(str,a,b,c))
+#define LOGNAME(c)         DOLOG(class_classref_or_classinfo_print(c))
+#define LOGMETHOD(str,m)   DOLOG(printf("%s", str); method_println(m);)
 #else
 #define LOG(str)
 #define LOG1(str,a)
@@ -236,50 +214,45 @@ bool typecheckverbose = false;
 #define LOGSTR1(str,a)
 #define LOGSTR2(str,a,b)
 #define LOGSTR3(str,a,b,c)
-#define LOGSTRu(utf)
 #define LOGNAME(c)
+#define LOGMETHOD(str,m)
 #endif
 
 #ifdef TYPECHECK_VERBOSE_IMPORTANT
-#define LOGimp(str)     DOLOG(log_text(str))
-#define LOGimpSTR(str)  DOLOG(log_plain(str))
-#define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
+#define LOGimp(str)     DOLOG(puts(str);LOGNL)
+#define LOGimpSTR(str)  DOLOG(puts(str))
 #else
 #define LOGimp(str)
 #define LOGimpSTR(str)
-#define LOGimpSTRu(utf)
 #endif
 
 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
 
 #include <stdio.h>
 
-static
-void
-typestack_print(FILE *file,stackptr stack)
+static void typecheck_print_var(FILE *file, jitdata *jd, s4 index)
 {
-#ifdef TYPEINFO_DEBUG
-    while (stack) {
-               /*fprintf(file,"<%p>",stack);*/
-        typeinfo_print_stacktype(file,stack->type,&(stack->typeinfo));
-        stack = stack->prev;
-        if (stack) fprintf(file," ");
-    }
-#endif
+       varinfo *var;
+
+       assert(index >= 0 && index < jd->varcount);
+       var = VAR(index);
+       typeinfo_print_type(file, var->type, &(var->typeinfo));
 }
 
-static
-void
-typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
+static void typecheck_print_vararray(FILE *file, jitdata *jd, s4 *vars, int len)
 {
-    fprintf(file,"Stack: ");
-    typestack_print(file,instack);
-    fprintf(file," Locals:");
-    typevectorset_print(file,localset,size);
+       s4 i;
+
+       for (i=0; i<len; ++i) {
+               if (i)
+                       fputc(' ', file);
+               typecheck_print_var(file, jd, *vars++);
+       }
 }
 
 #endif
 
+
 /****************************************************************************/
 /* STATISTICS                                                               */
 /****************************************************************************/
@@ -294,7 +267,6 @@ typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
 #define STAT_LOCALS      16
 
 static int stat_typechecked = 0;
-static int stat_typechecked_jsr = 0;
 static int stat_methods_with_handlers = 0;
 static int stat_methods_maythrow = 0;
 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
@@ -302,7 +274,6 @@ static int stat_reached = 0;
 static int stat_copied = 0;
 static int stat_merged = 0;
 static int stat_merging_changed = 0;
-static int stat_backwards = 0;
 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
 static int stat_locals[STAT_LOCALS+1] = { 0 };
 static int stat_ins = 0;
@@ -347,14 +318,12 @@ static void print_freq(FILE *file,int *array,int limit)
 
 void typecheck_print_statistics(FILE *file) {
        fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
-       fprintf(file,"    with JSR       : %8d\n",stat_typechecked_jsr);
        fprintf(file,"    with handler(s): %8d\n",stat_methods_with_handlers);
        fprintf(file,"    with throw(s)  : %8d\n",stat_methods_maythrow);
        fprintf(file,"reached blocks     : %8d\n",stat_reached);
        fprintf(file,"copied states      : %8d\n",stat_copied);
        fprintf(file,"merged states      : %8d\n",stat_merged);
        fprintf(file,"merging changed    : %8d\n",stat_merging_changed);
-       fprintf(file,"backwards branches : %8d\n",stat_backwards);
        fprintf(file,"handlers reached   : %8d\n",stat_handlers_reached);
        fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
        fprintf(file,"instructions       : %8d\n",stat_ins);
@@ -393,36 +362,50 @@ void typecheck_print_statistics(FILE *file) {
 #define TYPECHECK_COUNT_FREQ(array,val,limit)
 #endif
 
+
 /****************************************************************************/
 /* MACROS FOR THROWING EXCEPTIONS                                           */
 /****************************************************************************/
 
-#define TYPECHECK_VERIFYERROR_ret(m,msg,retval) \
-    do { \
-        *exceptionptr = new_verifyerror((m), (msg)); \
-        return (retval); \
+#define TYPECHECK_VERIFYERROR_ret(m,msg,retval)                      \
+    do {                                                             \
+        exceptions_throw_verifyerror((m), (msg));                    \
+        return (retval);                                             \
     } while (0)
 
 #define TYPECHECK_VERIFYERROR_main(msg)  TYPECHECK_VERIFYERROR_ret(state.m,(msg),NULL)
 #define TYPECHECK_VERIFYERROR_bool(msg)  TYPECHECK_VERIFYERROR_ret(state->m,(msg),false)
 
+
 /****************************************************************************/
-/* MACROS FOR STACK SLOT TYPE CHECKING                                      */
+/* MACROS FOR VARIABLE TYPE CHECKING                                        */
 /****************************************************************************/
 
-#define TYPECHECK_CHECK_TYPE(sp,tp,msg) \
-    do { \
-               if ((sp)->type != (tp)) { \
-               *exceptionptr = new_verifyerror(state->m, (msg)); \
-               return false; \
-               } \
+#define TYPECHECK_CHECK_TYPE(i,tp,msg)                               \
+    do {                                                             \
+        if (VAR(i)->type != (tp)) {                                  \
+            exceptions_throw_verifyerror(state->m, (msg));           \
+            return false;                                            \
+        }                                                            \
     } while (0)
 
-#define TYPECHECK_INT(sp)  TYPECHECK_CHECK_TYPE(sp,TYPE_INT,"Expected to find integer on stack")
-#define TYPECHECK_LNG(sp)  TYPECHECK_CHECK_TYPE(sp,TYPE_LNG,"Expected to find long on stack")
-#define TYPECHECK_FLT(sp)  TYPECHECK_CHECK_TYPE(sp,TYPE_FLT,"Expected to find float on stack")
-#define TYPECHECK_DBL(sp)  TYPECHECK_CHECK_TYPE(sp,TYPE_DBL,"Expected to find double on stack")
-#define TYPECHECK_ADR(sp)  TYPECHECK_CHECK_TYPE(sp,TYPE_ADR,"Expected to find object on stack")
+#define TYPECHECK_INT(i)                                             \
+    TYPECHECK_CHECK_TYPE(i,TYPE_INT,"Expected to find integer value")
+#define TYPECHECK_LNG(i)                                             \
+    TYPECHECK_CHECK_TYPE(i,TYPE_LNG,"Expected to find long value")
+#define TYPECHECK_FLT(i)                                             \
+    TYPECHECK_CHECK_TYPE(i,TYPE_FLT,"Expected to find float value")
+#define TYPECHECK_DBL(i)                                             \
+    TYPECHECK_CHECK_TYPE(i,TYPE_DBL,"Expected to find double value")
+#define TYPECHECK_ADR(i)                                             \
+    TYPECHECK_CHECK_TYPE(i,TYPE_ADR,"Expected to find object value")
+
+#define TYPECHECK_INT_OP(o)  TYPECHECK_INT((o).varindex)
+#define TYPECHECK_LNG_OP(o)  TYPECHECK_LNG((o).varindex)
+#define TYPECHECK_FLT_OP(o)  TYPECHECK_FLT((o).varindex)
+#define TYPECHECK_DBL_OP(o)  TYPECHECK_DBL((o).varindex)
+#define TYPECHECK_ADR_OP(o)  TYPECHECK_ADR((o).varindex)
+
 
 /****************************************************************************/
 /* VERIFIER STATE STRUCT                                                    */
@@ -432,35 +415,38 @@ void typecheck_print_statistics(FILE *file) {
 /* bytecode verifier for passing it between verifier functions.        */
 
 typedef struct verifier_state {
-    stackptr curstack;      /* input stack top for current instruction */
     instruction *iptr;               /* pointer to current instruction */
     basicblock *bptr;                /* pointer to current basic block */
 
        methodinfo *m;                               /* the current method */
+       jitdata *jd;                         /* jitdata for current method */
        codegendata *cd;                 /* codegendata for current method */
-       registerdata *rd;               /* registerdata for current method */
+
+       basicblock *basicblocks;
+       s4 basicblockcount;
        
        s4 numlocals;                         /* number of local variables */
        s4 validlocals;                /* number of Java-accessible locals */
-       void *localbuf;       /* local variable types for each block start */
-       typevector *localset;        /* typevector set for local variables */
-       typedescriptor returntype;    /* return type of the current method */
+       s4 *reverselocalmap;
        
-       stackptr savedstackbuf;             /* buffer for saving the stack */
-       stackptr savedstack;             /* saved instack of current block */
+       typedescriptor returntype;    /* return type of the current method */
+
+       s4 *savedindices;
+       s4 *savedinvars;                            /* saved invar pointer */
+
+       s4 exinvars;
        
     exceptiontable **handlers;            /* active exception handlers */
-       stackelement excstack;           /* instack for exception handlers */
        
     bool repeat;            /* if true, blocks are iterated over again */
     bool initmethod;             /* true if this is an "<init>" method */
-       bool jsrencountered;                 /* true if we there was a JSR */
 
 #ifdef TYPECHECK_STATISTICS
        bool stat_maythrow;          /* at least one instruction may throw */
 #endif
 } verifier_state;
 
+
 /****************************************************************************/
 /* TYPESTACK MACROS AND FUNCTIONS                                           */
 /*                                                                          */
@@ -474,30 +460,15 @@ typedef struct verifier_state {
 /* is kept as a linked list dangling off the typeinfo of the stack slot.    */
 /****************************************************************************/
 
-#define TYPESTACK_IS_RETURNADDRESS(sptr) \
-            TYPE_IS_RETURNADDRESS((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)
-
-/* typestack_copy **************************************************************
+/* typecheck_copy_types ********************************************************
  
-   Copy the types on the given stack to the destination stack.
+   Copy the types of the source variables to the destination variables.
 
-   This function does a straight forward copy except for returnAddress types.
-   For returnAddress slots only the return addresses corresponding to
-   typevectors in the SELECTED set are copied.
-   
    IN:
           state............current verifier state
-          y................stack with types to copy
-          selected.........set of selected typevectors
-
-   OUT:
-       *dst.............the destination stack
+          srcvars..........array of variable indices to copy
+          dstvars..........array of the destination variables
+          n................number of variables to copy
 
    RETURN VALUE:
        true.............success
@@ -506,258 +477,85 @@ typedef struct verifier_state {
 *******************************************************************************/
 
 static bool
-typestack_copy(verifier_state *state,stackptr dst,stackptr y,typevector *selected)
+typecheck_copy_types(verifier_state *state, s4 *srcvars, s4 *dstvars, s4 n)
 {
-       typevector *sel;
-       typeinfo_retaddr_set *sety;
-       typeinfo_retaddr_set *new;
-       typeinfo_retaddr_set **next;
-       int k;
-       
-       for (;dst; dst=dst->prev, y=y->prev) {
-               if (!y) {
-                       *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
-                       return false;
-               }
-               if (dst->type != y->type) {
-                       *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
-                       return false;
-               }
-               LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
-               if (dst->type == TYPE_ADDRESS) {
-                       if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
-                               /* We copy the returnAddresses from the selected
-                                * states only. */
-
-                               LOG("copying returnAddress");
-                               sety = TYPESTACK_RETURNADDRESSSET(y);
-                               next = &new;
-                               for (k=0,sel=selected; sel; sel=sel->alt) {
-                                       LOG1("selected k=%d",sel->k);
-                                       while (k<sel->k) {
-                                               sety = sety->alt;
-                                               k++;
-                                       }
-                                       *next = DNEW(typeinfo_retaddr_set);
-                                       (*next)->addr = sety->addr;
-                                       next = &((*next)->alt);
-                               }
-                               *next = NULL;
-                               TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
-                       }
-                       else {
-                               TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
-                       }
-               }
-       }
-       if (y) {
-               *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
-               return false;
-       }
-       return true;
-}
-
-/* typestack_put_retaddr *******************************************************
-   Put a returnAddress into a stack slot.
-
-   The stack slot receives a set of return addresses with as many members as
-   there are typevectors in the local variable set.
-
-   IN:
-          retaddr..........the returnAddress to set (a basicblock *)
-          loc..............the local variable typevector set
-
-   OUT:
-       *dst.............the destination stack slot
+       s4 i;
+       varinfo *sv;
+       varinfo *dv;
+       jitdata *jd = state->jd;
 
-*******************************************************************************/
+       for (i=0; i < n; ++i, ++srcvars, ++dstvars) {
+               sv = VAR(*srcvars);
+               dv = VAR(*dstvars);
 
-static void
-typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
-{
-       TYPECHECK_ASSERT(dst->type == TYPE_ADDRESS);
-       
-       TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
-       for (;loc; loc=loc->alt) {
-               typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
-               set->addr = retaddr;
-               set->alt = TYPESTACK_RETURNADDRESSSET(dst);
-               TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
+               dv->type = sv->type;
+               if (dv->type == TYPE_ADR) {
+                       TYPEINFO_CLONE(sv->typeinfo,dv->typeinfo);
+               }
        }
+       return true;
 }
 
-/* typestack_collapse **********************************************************
-   Collapse the given stack by shortening all return address sets to a single
-   member.
-
-   OUT:
-       *dst.............the destination stack to collapse
-
-*******************************************************************************/
-
-static void
-typestack_collapse(stackptr dst)
-{
-       for (; dst; dst = dst->prev) {
-               if (TYPESTACK_IS_RETURNADDRESS(dst))
-                       TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
-       }
-}
 
-/* typestack_merge *************************************************************
+/* typecheck_merge_types *******************************************************
  
-   Merge the types on one stack into the destination stack.
+   Merge the types of the source variables into the destination variables.
 
    IN:
        state............current state of the verifier
-          dst..............the destination stack
-          y................the second stack
-
-   OUT:
-       *dst.............receives the result of the stack merge
+          srcvars..........source variable indices
+          dstvars..........destination variable indices
+          n................number of variables
 
    RETURN VALUE:
-       typecheck_TRUE...*dst has been modified
-          typecheck_FALSE..*dst has not been modified
+       typecheck_TRUE...the destination variables have been modified
+          typecheck_FALSE..the destination variables are unchanged
           typecheck_FAIL...an exception has been thrown
 
 *******************************************************************************/
 
 static typecheck_result
-typestack_merge(verifier_state *state,stackptr dst,stackptr y)
+typecheck_merge_types(verifier_state *state,s4 *srcvars, s4 *dstvars, s4 n)
 {
+       s4 i;
+       varinfo *sv;
+       varinfo *dv;
+       jitdata *jd = state->jd;
        typecheck_result r;
        bool changed = false;
        
-       for (; dst; dst = dst->prev, y=y->prev) {
-               if (!y) {
-                       *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
-                       return typecheck_FAIL;
-               }
-               if (dst->type != y->type) {
-                       *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
+       for (i=0; i < n; ++i, ++srcvars, ++dstvars) {
+               sv = VAR(*srcvars);
+               dv = VAR(*dstvars);
+
+               if (dv->type != sv->type) {
+                       exceptions_throw_verifyerror(state->m,"Stack type mismatch");
                        return typecheck_FAIL;
                }
-               if (dst->type == TYPE_ADDRESS) {
-                       if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
-                               /* dst has returnAddress type */
-                               if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
-                                       *exceptionptr = new_verifyerror(state->m,"Merging returnAddress with reference");
+               if (dv->type == TYPE_ADR) {
+                       if (TYPEINFO_IS_PRIMITIVE(dv->typeinfo)) {
+                               /* dv has returnAddress type */
+                               if (!TYPEINFO_IS_PRIMITIVE(sv->typeinfo)) {
+                                       exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
                                        return typecheck_FAIL;
                                }
                        }
                        else {
-                               /* dst has reference type */
-                               if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
-                                       *exceptionptr = new_verifyerror(state->m,"Merging reference with returnAddress");
+                               /* dv has reference type */
+                               if (TYPEINFO_IS_PRIMITIVE(sv->typeinfo)) {
+                                       exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
                                        return typecheck_FAIL;
                                }
-                               r = typeinfo_merge(state->m,&(dst->typeinfo),&(y->typeinfo));
+                               r = typeinfo_merge(state->m,&(dv->typeinfo),&(sv->typeinfo));
                                if (r == typecheck_FAIL)
                                        return r;
                                changed |= r;
                        }
                }
        }
-       if (y) {
-               *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
-               return typecheck_FAIL;
-       }
        return changed;
 }
 
-/* typestack_add ***************************************************************
-   Add the return addresses in the given stack at a given k-index to the
-   corresponding return address sets in the destination stack.
-
-   IN:
-          dst..............the destination stack
-          y................the second stack
-          ky...............the k-index which should be selected from the Y stack
-
-   OUT:
-       *dst.............receives the result of adding the addresses
-
-*******************************************************************************/
-
-static void
-typestack_add(stackptr dst,stackptr y,int ky)
-{
-       typeinfo_retaddr_set *setd;
-       typeinfo_retaddr_set *sety;
-       
-       for (; dst; dst = dst->prev, y=y->prev) {
-               if (TYPESTACK_IS_RETURNADDRESS(dst)) {
-                       setd = TYPESTACK_RETURNADDRESSSET(dst);
-                       sety = TYPESTACK_RETURNADDRESSSET(y);
-                       RETURNADDRESSSET_SEEK(sety,ky);
-                       while (setd->alt)
-                               setd=setd->alt;
-                       setd->alt = DNEW(typeinfo_retaddr_set);
-                       setd->alt->addr = sety->addr;
-                       setd->alt->alt = NULL;
-               }
-       }
-}
-
-/* XXX document */
-/* 'a' and 'b' are assumed to have passed typestack_canmerge! */
-static bool
-typestack_separable_with(stackptr a,stackptr b,int kb)
-{
-       typeinfo_retaddr_set *seta;
-       typeinfo_retaddr_set *setb;
-       
-       for (; a; a = a->prev, b = b->prev) {
-               TYPECHECK_ASSERT(b);
-               if (TYPESTACK_IS_RETURNADDRESS(a)) {
-                       TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
-                       seta = TYPESTACK_RETURNADDRESSSET(a);
-                       setb = TYPESTACK_RETURNADDRESSSET(b);
-                       RETURNADDRESSSET_SEEK(setb,kb);
-
-                       for (;seta;seta=seta->alt)
-                               if (seta->addr != setb->addr) return true;
-               }
-       }
-       TYPECHECK_ASSERT(!b);
-       return false;
-}
-
-/* XXX document */
-/* 'a' and 'b' are assumed to have passed typestack_canmerge! */
-static bool
-typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
-{
-       typeinfo_retaddr_set *seta;
-       typeinfo_retaddr_set *setb;
-
-       for (; a; a = a->prev, b = b->prev) {
-               TYPECHECK_ASSERT(b);
-               if (TYPESTACK_IS_RETURNADDRESS(a)) {
-                       TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
-                       seta = TYPESTACK_RETURNADDRESSSET(a);
-                       setb = TYPESTACK_RETURNADDRESSSET(b);
-                       RETURNADDRESSSET_SEEK(seta,ka);
-                       RETURNADDRESSSET_SEEK(setb,kb);
-
-                       if (seta->addr != setb->addr) return true;
-               }
-       }
-       TYPECHECK_ASSERT(!b);
-       return false;
-}
-
-/****************************************************************************/
-/* TYPESTATE FUNCTIONS                                                      */
-/*                                                                          */
-/* These functions act on the 'type state', which comprises:                */
-/*     - the types of the stack slots of the current stack                  */
-/*     - the set of type vectors describing the local variables             */
-/****************************************************************************/
 
 /* typestate_merge *************************************************************
  
@@ -765,14 +563,11 @@ typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
 
    IN:
        state............current state of the verifier
-          deststack........the destination stack
-          destloc..........the destination set of local variable typevectors
-          ystack...........the second stack
-          yloc.............the second set of local variable typevectors
-
-   OUT:
-       *deststack.......receives the result of the stack merge
-          *destloc.........receives the result of the local variable merge
+          dstvars..........indices of the destinations invars
+          dstlocals........the destinations inlocals
+          srcvars..........indices of the source's outvars
+          srclocals........the source locals
+          n................number of invars (== number of outvars)
 
    RETURN VALUE:
        typecheck_TRUE...destination state has been modified
@@ -783,99 +578,30 @@ typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
 
 static typecheck_result
 typestate_merge(verifier_state *state,
-                               stackptr deststack,typevector *destloc,
-                               stackptr ystack,typevector *yloc)
+                               s4 *srcvars, varinfo *srclocals,
+                               s4 *dstvars, varinfo *dstlocals,
+                               s4 n)
 {
-       typevector *dvec,*yvec;
-       int kd,ky;
        bool changed = false;
        typecheck_result r;
        
-       LOG("merge:");
-       LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
-       LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
-       LOGSTR("dloc  : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
-       LOGSTR("yloc  : "); DOLOG(typevectorset_print(get_logfile(),yloc,state->numlocals)); LOGNL;
-       LOGFLUSH;
-
        /* The stack is always merged. If there are returnAddresses on
         * the stack they are ignored in this step. */
 
-       r = typestack_merge(state,deststack,ystack);
+       r = typecheck_merge_types(state, srcvars, dstvars, n);
        if (r == typecheck_FAIL)
                return r;
        changed |= r;
 
-       /* If there have not been any JSRs we just have a single typevector merge */
-       if (!state->jsrencountered) {
-               r = typevector_merge(state->m,destloc,yloc,state->numlocals);
-               if (r == typecheck_FAIL)
-                       return r;
-               return changed | r;
-       }
-
-       for (yvec=yloc; yvec; yvec=yvec->alt) {
-               ky = yvec->k;
-
-               /* Check if the typestates (deststack,destloc) will be
-                * separable when (ystack,yvec) is added. */
-
-               if (!typestack_separable_with(deststack,ystack,ky)
-                       && !typevectorset_separable_with(destloc,yvec,state->numlocals))
-               {
-                       /* No, the resulting set won't be separable, thus we
-                        * may merge all states in (deststack,destloc) and
-                        * (ystack,yvec). */
-
-                       typestack_collapse(deststack);
-                       if (typevectorset_collapse(state->m,destloc,state->numlocals) == typecheck_FAIL)
-                               return typecheck_FAIL;
-                       if (typevector_merge(state->m,destloc,yvec,state->numlocals) == typecheck_FAIL)
-                               return typecheck_FAIL;
-               }
-               else {
-                       /* Yes, the resulting set will be separable. Thus we check
-                        * if we may merge (ystack,yvec) with a single state in
-                        * (deststack,destloc). */
-               
-                       for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
-                               if (!typestack_separable_from(ystack,ky,deststack,kd)
-                                       && !typevector_separable_from(yvec,dvec,state->numlocals))
-                               {
-                                       /* The typestate (ystack,yvec) is not separable from
-                                        * (deststack,dvec) by any returnAddress. Thus we may
-                                        * merge the states. */
-                                       
-                                       r = typevector_merge(state->m,dvec,yvec,state->numlocals);
-                                       if (r == typecheck_FAIL)
-                                               return r;
-                                       changed |= r;
-                                       
-                                       goto merged;
-                               }
-                       }
-
-                       /* The typestate (ystack,yvec) is separable from all typestates
-                        * (deststack,destloc). Thus we must add this state to the
-                        * result set. */
+       /* merge the locals */
 
-                       typestack_add(deststack,ystack,ky);
-                       typevectorset_add(destloc,yvec,state->numlocals);
-                       changed = true;
-               }
-                  
-       merged:
-               ;
-       }
-       
-       LOG("result:");
-       LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
-       LOGSTR("dloc  : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
-       LOGFLUSH;
-       
-       return changed;
+       r = typevector_merge(state->m, dstlocals, srclocals, state->numlocals);
+       if (r == typecheck_FAIL)
+               return r;
+       return changed | r;
 }
 
+
 /* typestate_reach *************************************************************
  
    Reach a destination block and propagate stack and local variable types
@@ -883,8 +609,9 @@ typestate_merge(verifier_state *state,
    IN:
        state............current state of the verifier
           destblock........destination basic block
-          ystack...........stack to propagate
-          yloc.............set of local variable typevectors to propagate
+          srcvars..........variable indices of the outvars to propagate
+          srclocals........local variables to propagate
+          n................number of srcvars
 
    OUT:
        state->repeat....set to true if the verifier must iterate again
@@ -899,65 +626,36 @@ typestate_merge(verifier_state *state,
 static bool
 typestate_reach(verifier_state *state,
                                basicblock *destblock,
-                               stackptr ystack,typevector *yloc)
+                               s4 *srcvars, varinfo *srclocals, s4 n)
 {
-       typevector *destloc;
-       int destidx;
+       varinfo *destloc;
        bool changed = false;
        typecheck_result r;
 
-       LOG1("reaching block L%03d",destblock->debug_nr);
+       LOG1("reaching block L%03d",destblock->nr);
        TYPECHECK_COUNT(stat_reached);
        
-       destidx = destblock - state->cd->method->basicblocks;
-       destloc = MGET_TYPEVECTOR(state->localbuf,destidx,state->numlocals);
-
-       /* When branching backwards we have to check for uninitialized objects */
-       
-       if (destblock <= state->bptr) {
-               stackptr sp;
-               int i;
-
-               /* XXX FIXME FOR INLINING */
-
-               if (!useinlining) {
-                       TYPECHECK_COUNT(stat_backwards);
-                       LOG("BACKWARDS!");
-                       for (sp = ystack; sp; sp=sp->prev)
-                               if (sp->type == TYPE_ADR &&
-                               TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
-                                       /*printf("current: %d, dest: %d\n", state->bptr->debug_nr, destblock->debug_nr);*/
-                                       *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object on stack");
-                                       return false;
-                               }
+       destloc = destblock->inlocals;
 
-                       for (i=0; i<state->numlocals; ++i)
-                               if (yloc->td[i].type == TYPE_ADR &&
-                                       TYPEINFO_IS_NEWOBJECT(yloc->td[i].info)) {
-                                       *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object in local variable");
-                                       return false;
-                               }
-               }
-       }
-       
        if (destblock->flags == BBTYPECHECK_UNDEF) {
                /* The destblock has never been reached before */
 
                TYPECHECK_COUNT(stat_copied);
-               LOG1("block (index %04d) reached first time",destidx);
+               LOG1("block L%03d reached first time",destblock->nr);
                
-               if (!typestack_copy(state,destblock->instack,ystack,yloc))
+               if (!typecheck_copy_types(state, srcvars, destblock->invars, n))
                        return false;
-               typevectorset_copy_inplace(yloc,destloc,state->numlocals);
+               typevector_copy_inplace(srclocals, destloc, state->numlocals);
                changed = true;
        }
        else {
                /* The destblock has already been reached before */
                
                TYPECHECK_COUNT(stat_merged);
-               LOG1("block (index %04d) reached before",destidx);
+               LOG1("block L%03d reached before", destblock->nr);
                
-               r = typestate_merge(state,destblock->instack,destloc,ystack,yloc);
+               r = typestate_merge(state, srcvars, srclocals, 
+                               destblock->invars, destblock->inlocals, n);
                if (r == typecheck_FAIL)
                        return false;
                changed = r;
@@ -975,58 +673,57 @@ typestate_reach(verifier_state *state,
        return true;
 }
 
-/* typestate_ret ***************************************************************
+
+/* typestate_save_invars *******************************************************
  
-   Reach the destinations of a RET instruction.
+   Save the invars of the current basic block in the space reserved by
+   parse.
+
+   This function must be called before an instruction modifies a variable
+   that is an invar of the current block. In such cases the invars of the
+   block must be saved, and restored at the end of the analysis of this
+   basic block, so that the invars again reflect the *input* to this basic
+   block (and do not randomly contain types that appear within the block).
 
    IN:
        state............current state of the verifier
-          retindex.........index of local variable containing the returnAddress
-
-   OUT:
-       state->repeat....set to true if the verifier must iterate again
-                           over the basic blocks
-          
-   RETURN VALUE:
-       true.............success
-          false............an exception has been thrown
 
 *******************************************************************************/
 
-static bool
-typestate_ret(verifier_state *state,int retindex)
+static void
+typestate_save_invars(verifier_state *state)
 {
-       typevector *yvec;
-       typevector *selected;
-       basicblock *destblock;
+       s4 i, index;
+       s4 *pindex;
+       
+       LOG("saving invars");
+
+       if (!state->savedindices) {
+               LOG("allocating savedindices buffer");
+               pindex = DMNEW(s4, state->m->maxstack);
+               state->savedindices = pindex;
+               index = state->numlocals + VERIFIER_EXTRA_VARS;
+               for (i=0; i<state->m->maxstack; ++i)
+                       *pindex++ = index++;
+       }
 
-       for (yvec=state->localset; yvec; ) {
-               if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex])) {
-                       *exceptionptr = new_verifyerror(state->m,"Illegal instruction: RET on non-returnAddress");
-                       return false;
-               }
+       /* save types */
 
-               destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
+       typecheck_copy_types(state, state->bptr->invars, state->savedindices, 
+                       state->bptr->indepth);
 
-               selected = typevectorset_select(&yvec,retindex,destblock);
-               
-               if (!typestate_reach(state,destblock,state->curstack,selected))
-                       return false;
-       }
-       return true;
+       /* set the invars of the block to the saved variables */
+       /* and remember the original invars                   */
+
+       state->savedinvars = state->bptr->invars;
+       state->bptr->invars = state->savedindices;
 }
 
-/* typestate_save_instack ******************************************************
-   Save the input stack of the current basic block in the "savedstackbuf"
-   of the verifier state.
 
-   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).
+/* typestate_restore_invars  ***************************************************
+   Restore the invars of the current basic block that have been previously
+   saved by `typestate_save_invars`.
 
    IN:
        state............current state of the verifier
@@ -1034,69 +731,37 @@ typestate_ret(verifier_state *state,int retindex)
 *******************************************************************************/
 
 static void
-typestate_save_instack(verifier_state *state)
+typestate_restore_invars(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);
-       }
-}
+       TYPECHECK_COUNT(stat_savedstack);
+       LOG("restoring saved invars");
 
-/* typestate_restore_instack ***************************************************
-   Restore the input stack of the current basic block that has been previously
-   saved by `typestate_save_instack`.
+       /* restore the invars pointer */
 
-   IN:
-       state............current state of the verifier
+       state->bptr->invars = state->savedinvars;
 
-*******************************************************************************/
+       /* copy the types back */
 
-static void
-typestate_restore_instack(verifier_state *state)
-{
-       stackptr sp;
-       stackptr dest;
-       
-       TYPECHECK_COUNT(stat_savedstack);
-       LOG("restoring saved instack");
+       typecheck_copy_types(state, state->savedindices, state->bptr->invars,
+                       state->bptr->indepth);
 
-       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);
-       }
+       /* mark that there are no saved invars currently */
 
-       state->bptr->instack = state->savedstack;
-       state->savedstack = NULL;
+       state->savedinvars = NULL;
 }
 
+
 /****************************************************************************/
 /* MISC MACROS                                                              */
 /****************************************************************************/
 
-#define COPYTYPE(source,dest)   \
-       {if ((source)->type == TYPE_ADR)                                                                \
-                       TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
+#define COPYTYPE(source,dest)                                        \
+    {if (VAROP(source)->type == TYPE_ADR)                            \
+            TYPEINFO_COPY(VAROP(source)->typeinfo,VAROP(dest)->typeinfo);}
 
 #define ISBUILTIN(v)   (bte->fp == (functionptr) (v))
 
+
 /* verify_invocation ***********************************************************
  
    Verify an ICMD_INVOKE* instruction.
@@ -1115,24 +780,61 @@ verify_invocation(verifier_state *state)
 {
        unresolved_method *um;      /* struct describing the called method */
        constant_FMIref *mref;           /* reference to the called method */
+       methodinfo *mi;                        /* resolved method (if any) */
        methoddesc *md;                 /* descriptor of the called method */
+       utf *mname;                                         /* method name */
+       utf *mclassname;                     /* name of the method's class */
        bool specialmethod;            /* true if a <...> method is called */
        int opcode;                                   /* invocation opcode */
        bool callinginit;                      /* true if <init> is called */
        instruction *ins;
        classref_or_classinfo initclass;
        typedesc *td;
-       stackelement *stack;                    /* temporary stack pointer */
-       stackelement *dst;               /* result stack of the invocation */
+       s4 argindex;                            /* argument variable index */
+       varinfo *av;                                  /* argument variable */
+       varinfo *dv;                  /* result variable of the invocation */
        int i;                                                  /* counter */
     u1 rtype;                          /* return type of called method */
+       resolve_result_t result;
+       jitdata *jd;
+       bool invokespecial;
+
+       jd = state->jd;
+
+       /* get the FMIref and the unresolved_method struct (if any) */
+       /* from the instruction                                     */
+
+       if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
+               /* unresolved method */
+               um = state->iptr->sx.s23.s3.um;
+               mref = um->methodref;
+       }
+       else {
+               /* resolved method */
+               um = NULL;
+               mref = state->iptr->sx.s23.s3.fmiref;
+       }
+
+       /* get method descriptor and name */
 
-       um = (unresolved_method *) state->iptr[0].target;
-       mref = um->methodref;
        md = mref->parseddesc.md;
-       specialmethod = (mref->name->text[0] == '<');
+       mname = mref->name;
+
+       /* get method info (if resolved) and classname */
+
+       if (IS_FMIREF_RESOLVED(mref)) {
+               mi = mref->p.method;
+               mclassname = mi->class->name;
+       }
+       else {
+               mi = NULL;
+               mclassname = mref->p.classref->name;
+       }
+
        opcode = state->iptr[0].opc;
-       dst = state->iptr->dst;
+       invokespecial = (opcode == ICMD_INVOKESPECIAL);
+       specialmethod = (mname->text[0] == '<');
+       dv = VAROP(state->iptr->dst);
 
        /* prevent compiler warnings */
 
@@ -1140,7 +842,7 @@ verify_invocation(verifier_state *state)
 
        /* check whether we are calling <init> */
        
-       callinginit = (opcode == ICMD_INVOKESPECIAL && mref->name == utf_init);
+       callinginit = (invokespecial && mname == utf_init);
        if (specialmethod && !callinginit)
                TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
 
@@ -1153,26 +855,29 @@ verify_invocation(verifier_state *state)
 
        /* check parameter types */
 
-       stack = state->curstack;
        i = md->paramcount; /* number of parameters including 'this'*/
        while (--i >= 0) {
                LOG1("param %d",i);
+               argindex = state->iptr->sx.s23.s2.args[i];
+               av = VAR(argindex);
                td = md->paramtypes + i;
-               if (stack->type != td->type)
+
+               if (av->type != td->type)
                        TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
-               if (stack->type == TYPE_ADR) {
-                       LOGINFO(&(stack->typeinfo));
+
+               if (av->type == TYPE_ADR) {
+                       LOGINFO(&(av->typeinfo));
                        if (i==0 && callinginit)
                        {
                                /* first argument to <init> method */
-                               if (!TYPEINFO_IS_NEWOBJECT(stack->typeinfo))
+                               if (!TYPEINFO_IS_NEWOBJECT(av->typeinfo))
                                        TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
 
                                /* get the address of the NEW instruction */
-                               LOGINFO(&(stack->typeinfo));
-                               ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo);
+                               LOGINFO(&(av->typeinfo));
+                               ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo);
                                if (ins)
-                                       initclass = CLASSREF_OR_CLASSINFO(ins[-1].target);
+                                       initclass = ins[-1].sx.val.c;
                                else
                                        initclass.cls = state->m->class;
                                LOGSTR("class: "); LOGNAME(initclass); LOGNL;
@@ -1186,45 +891,43 @@ verify_invocation(verifier_state *state)
                        }
                }
                LOG("ok");
-
-               if (i)
-                       stack = stack->prev;
-       }
-
-       LOG("checking return type");
-       rtype = md->returntype.type;
-       if (rtype != TYPE_VOID) {
-               if (rtype != dst->type)
-                       TYPECHECK_VERIFYERROR_bool("Return type mismatch in method invocation");
-               if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
-                       return false;
        }
 
        if (callinginit) {
                LOG("replacing uninitialized object");
                /* replace uninitialized object type on stack */
-               stack = dst;
-               while (stack) {
-                       if (stack->type == TYPE_ADR
-                                       && TYPEINFO_IS_NEWOBJECT(stack->typeinfo)
-                                       && TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo) == ins)
+
+               /* for all live-in and live-through variables */ 
+               for (i=0; i<state->iptr->s1.argcount; ++i) {
+                       argindex = state->iptr->sx.s23.s2.args[i];
+                       av = VAR(argindex);
+                       if (av->type == TYPE_ADR
+                                       && TYPEINFO_IS_NEWOBJECT(av->typeinfo)
+                                       && TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo) == ins)
                        {
-                               LOG("replacing uninitialized type on stack");
+                               LOG("replacing uninitialized type");
 
                                /* If this stackslot is in the instack of
                                 * this basic block we must save the type(s)
                                 * we are going to replace.
                                 */
-                               if (stack <= state->bptr->instack && !state->savedstack)
-                                       typestate_save_instack(state);
+                               /* XXX this needs a new check */
+                               if (state->bptr->invars
+                                               && argindex >= state->bptr->invars[0] 
+                                               && argindex < state->bptr->varstart 
+                                               && !state->savedinvars)
+                               {
+                                       typestate_save_invars(state);
+                               }
 
-                               if (!typeinfo_init_class(&(stack->typeinfo),initclass))
+                               if (!typeinfo_init_class(&(av->typeinfo),initclass))
                                        return false;
                        }
-                       stack = stack->prev;
                }
+
                /* replace uninitialized object type in locals */
-               if (!typevectorset_init_object(state->localset,ins,initclass,state->numlocals))
+               if (!typevector_init_object(state->jd->var, ins, initclass,
+                                       state->numlocals))
                        return false;
 
                /* initializing the 'this' reference? */
@@ -1235,8 +938,13 @@ verify_invocation(verifier_state *state)
                        /* must be <init> of current class or direct superclass                   */
                        /* the current class is linked, so must be its superclass. thus we can be */
                        /* sure that resolving will be trivial.                                   */
-                       if (!resolve_classref(state->m,mref->classref,resolveLazy,false,true,&cls))
-                               return false; /* exception */
+                       if (mi) {
+                               cls = mi->class;
+                       }
+                       else {
+                               if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
+                                       return false; /* exception */
+                       }
 
                        /* if lazy resolving did not succeed, it's not one of the allowed classes */
                        /* otherwise we check it directly                                         */
@@ -1246,29 +954,94 @@ verify_invocation(verifier_state *state)
 
                        /* set our marker variable to type int */
                        LOG("setting <init> marker");
-                       typevectorset_store(state->localset,state->numlocals-1,TYPE_INT,NULL);
+                       typevector_store(jd->var, state->numlocals-1, TYPE_INT, NULL);
                }
                else {
                        /* { we are initializing an instance created with NEW } */
-                       if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mref->classref->name) {
+                       if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mclassname) {
                                TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
                        }
                }
        }
 
-       /* record subtype constraints for parameters */
-       
-       if (!constrain_unresolved_method(um,state->m->class,state->m,state->iptr,state->curstack))
-               return false; /* XXX maybe wrap exception */
-
        /* try to resolve the method lazily */
-       
-       if (!resolve_method(um,resolveLazy,(methodinfo **) &(state->iptr[0].val.a)))
+
+       result = resolve_method_lazy(state->m, mref, invokespecial);
+
+       /* if resolved, perform verification checks */
+
+       if (result == resolveSucceeded) {
+
+               assert(IS_FMIREF_RESOLVED(mref));
+
+               mi = mref->p.method;
+
+               result = resolve_method_verifier_checks(jd,
+                                                                                               state->m, 
+                                                                                               mref,
+                                                                                               mi->class,
+                                                                                               mi,
+                                                                                               state->iptr->opc == ICMD_INVOKESTATIC,
+                                                                                               invokespecial,
+                                                                                               state->iptr);
+       }
+
+       /* if resolved, impose loading constraints */
+
+       if (result == resolveSucceeded) {
+               /* XXX state->m->class may have to be wrong when inlining */
+               if (!resolve_method_loading_constraints(state->m->class, mi))
+                       return false;
+       }
+
+       if (result == resolveFailed)
                return false;
 
+       if (result == resolveSucceeded) {
+               /* if this call is monomorphic, turn it into an INVOKESPECIAL */
+
+               if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
+                       && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
+               {
+                       state->iptr->opc = ICMD_INVOKESPECIAL;
+               }
+       }
+       else {
+               /* resolution must be deferred */
+
+               if (!um) {
+                       um = resolve_create_unresolved_method(state->m->class, state->m,
+                                       mref, 
+                                       state->iptr->opc == ICMD_INVOKESTATIC,
+                                       invokespecial);
+
+                       if (!um)
+                               return false;
+               }
+
+               /* record subtype constraints for parameters */
+
+               if (!constrain_unresolved_method(jd, um, state->m->class, 
+                                       state->m, state->iptr))
+                       return false; /* XXX maybe wrap exception */
+
+               /* store the unresolved_method pointer */
+
+               state->iptr->sx.s23.s3.um = um;
+               state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+       }
+
+       rtype = md->returntype.type;
+       if (rtype != TYPE_VOID) {
+               dv->type = rtype;
+               if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
+                       return false;
+       }
+
        return true;
 }
 
+
 /* verify_generic_builtin ******************************************************
  
    Verify the call of a generic builtin method.
@@ -1289,49 +1062,49 @@ verify_generic_builtin(verifier_state *state)
        s4 i;
        u1 rtype;
        methoddesc *md;
-    stackptr sp;
+    varinfo *av;
+       jitdata *jd = state->jd;
 
        TYPECHECK_COUNT(stat_ins_builtin_gen);
 
-       bte = (builtintable_entry *) state->iptr[0].val.a;
+       bte = state->iptr->sx.s23.s3.bte;
        md = bte->md;
        i = md->paramcount;
        
        /* check the types of the arguments on the stack */
 
-       sp = state->curstack;
        for (i--; i >= 0; i--) {
-               if (sp->type != md->paramtypes[i].type) {
+               av = VAR(state->iptr->sx.s23.s2.args[i]);
+
+               if (av->type != md->paramtypes[i].type) {
                        TYPECHECK_VERIFYERROR_bool("parameter type mismatch for builtin method");
                }
                
 #ifdef TYPECHECK_DEBUG
                /* generic builtins may only take primitive types and java.lang.Object references */
-               if (sp->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
+               if (av->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
                        *exceptionptr = new_internalerror("generic builtin method with non-generic reference parameter");
                        return false;
                }
 #endif
-               
-               sp = sp->prev;
        }
 
-       /* check the return type */
+       /* set the return type */
 
        rtype = md->returntype.type;
        if (rtype != TYPE_VOID) {
-               stackptr dst;
+               varinfo *dv;
 
-               dst = state->iptr->dst;
-               if (rtype != dst->type)
-                       TYPECHECK_VERIFYERROR_bool("Return type mismatch in generic builtin invocation");
-               if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
+               dv = VAROP(state->iptr->dst);
+               dv->type = rtype;
+               if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
                        return false;
        }
 
        return true;
 }
 
+
 /* verify_builtin **************************************************************
  
    Verify the call of a builtin method.
@@ -1350,10 +1123,11 @@ verify_builtin(verifier_state *state)
 {
        builtintable_entry *bte;
     classref_or_classinfo cls;
-    stackptr dst;               /* output stack of current instruction */
+    varinfo *dv;               /* output variable of current instruction */
+       jitdata *jd = state->jd;
 
-       bte = (builtintable_entry *) state->iptr[0].val.a;
-       dst = state->iptr->dst;
+       bte = state->iptr->sx.s23.s3.bte;
+       dv = VAROP(state->iptr->dst);
 
        /* XXX this is an ugly if-chain but twisti did not want a function */
        /* pointer in builtintable_entry for this, so here you go.. ;)     */
@@ -1361,54 +1135,65 @@ verify_builtin(verifier_state *state)
        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].target;
-               TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,state->iptr);
+               cls = state->iptr[-1].sx.val.c;
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_NEWOBJECT(dv->typeinfo,state->iptr);
        }
        else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BOOLEAN);
        }
        else if (ISBUILTIN(BUILTIN_newarray_char)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_CHAR);
        }
        else if (ISBUILTIN(BUILTIN_newarray_float)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_FLOAT);
        }
        else if (ISBUILTIN(BUILTIN_newarray_double)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_DOUBLE);
        }
        else if (ISBUILTIN(BUILTIN_newarray_byte)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BYTE);
        }
        else if (ISBUILTIN(BUILTIN_newarray_short)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_SHORT);
        }
        else if (ISBUILTIN(BUILTIN_newarray_int)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_INT);
        }
        else if (ISBUILTIN(BUILTIN_newarray_long)) {
-               TYPECHECK_INT(state->curstack);
-               TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               dv->type = TYPE_ADR;
+               TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_LONG);
        }
        else if (ISBUILTIN(BUILTIN_newarray))
        {
-               TYPECHECK_INT(state->curstack->prev);
-               if (state->iptr[-1].opc != ICMD_ACONST || !state->iptr[-1].target)
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+               if (state->iptr[-1].opc != ICMD_ACONST)
                        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));
+               dv->type = TYPE_ADR;
+               typeinfo_init_class(&(dv->typeinfo),state->iptr[-1].sx.val.c);
        }
        else if (ISBUILTIN(BUILTIN_arrayinstanceof))
        {
-               TYPECHECK_ADR(state->curstack->prev);
+               TYPECHECK_ADR(state->iptr->sx.s23.s2.args[0]);
                if (state->iptr[-1].opc != ICMD_ACONST)
                        TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
+               dv->type = TYPE_INT;
                /* XXX check that it is an array class(ref) */
        }
        else {
@@ -1417,6 +1202,7 @@ verify_builtin(verifier_state *state)
        return true;
 }
 
+
 /* verify_multianewarray *******************************************************
  
    Verify a MULTIANEWARRAY instruction.
@@ -1433,37 +1219,33 @@ verify_builtin(verifier_state *state)
 static bool
 verify_multianewarray(verifier_state *state)
 {
-    stackptr sp;
        classinfo *arrayclass;
        arraydescriptor *desc;
        s4 i;
+       jitdata *jd = state->jd;
 
        /* check the array lengths on the stack */
-       i = state->iptr[0].op1;
+       i = state->iptr->s1.argcount;
        if (i < 1)
                TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
 
-       sp = state->curstack;
        while (i--) {
-               if (!sp)
-                       TYPECHECK_VERIFYERROR_bool("Unable to pop operand off an empty stack");
-               TYPECHECK_INT(sp);
-               sp = sp->prev;
+               TYPECHECK_INT(state->iptr->sx.s23.s2.args[i]);
        }
 
        /* check array descriptor */
-       if (state->iptr[0].target == NULL) {
+       if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
                /* the array class reference has already been resolved */
-               arrayclass = (classinfo *) state->iptr[0].val.a;
+               arrayclass = state->iptr->sx.s23.s3.c.cls;
                if (!arrayclass)
                        TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
                if ((desc = arrayclass->vftbl->arraydesc) == NULL)
                        TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
-               if (desc->dimension < state->iptr[0].op1)
+               if (desc->dimension < state->iptr->s1.argcount)
                        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(&(VAROP(state->iptr->dst)->typeinfo), arrayclass);
        }
        else {
                const char *p;
@@ -1471,7 +1253,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 = state->iptr->sx.s23.s3.c.ref;
                i = 0;
                p = cr->name->text;
                while (p[i] == '[')
@@ -1479,18 +1261,85 @@ verify_multianewarray(verifier_state *state)
                /* { the dimension of the array class == i } */
                if (i < 1)
                        TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
-               if (i < state->iptr[0].op1)
+               if (i < state->iptr->s1.argcount)
                        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(&(VAROP(state->iptr->dst)->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
                        return false;
        }
 
+       /* set return type */
+
+       VAROP(state->iptr->dst)->type = TYPE_ADR;
+
        /* everything ok */
        return true;
 }
 
+
+/* typecheck_invalidate_locals *************************************************
+   Invalidate locals that are overwritten by writing to the given local.
+  
+   IN:
+       state............the current state of the verifier
+          index............the index of the local that is written
+          twoword..........true, if a two-word type is written
+
+*******************************************************************************/
+
+static void typecheck_invalidate_locals(verifier_state *state, s4 index, bool twoword)
+{
+       s4 i;
+       s4 t;
+       s4 mapped;
+       jitdata *jd = state->jd;
+       s4 *localmap = jd->local_map;
+       varinfo *vars = jd->var;
+
+       i = state->reverselocalmap[index];
+
+       /* invalidate locals of two-word type at index i-1 */
+
+       if (i > 0) {
+               localmap += 5 * (i-1);
+               for (t=0; t<5; ++t) {
+                       mapped = *localmap++;
+                       if (mapped >= 0 && IS_2_WORD_TYPE(vars[mapped].type)) {
+                               LOG1("invalidate local %d", mapped);
+                               vars[mapped].type = TYPE_VOID;
+                       }
+               }
+       }
+       else {
+               localmap += 5 * i;
+       }
+
+       /* invalidate locals at index i */
+
+       for (t=0; t<5; ++t) {
+               mapped = *localmap++;
+               if (mapped >= 0) {
+                       LOG1("invalidate local %d", mapped);
+                       vars[mapped].type = TYPE_VOID;
+               }
+       }
+
+       /* if a two-word type is written, invalidate locals at index i+1 */
+
+       if (twoword) {
+               for (t=0; t<5; ++t) {
+                       mapped = *localmap++;
+                       if (mapped >= 0) {
+                               LOG1("invalidate local %d", mapped);
+                               vars[mapped].type = TYPE_VOID;
+                       }
+               }
+       }
+}
+
+
 /* verify_basic_block **********************************************************
  
    Perform bytecode verification of a basic block.
@@ -1510,68 +1359,49 @@ verify_basic_block(verifier_state *state)
     int opcode;                                      /* current opcode */
     int len;                        /* for counting instructions, etc. */
     bool superblockend;        /* true if no fallthrough to next block */
+       instruction *iptr;                      /* the current instruction */
     basicblock *tbptr;                   /* temporary for target block */
-    stackptr dst;               /* output stack of current instruction */
-    basicblock **tptr;    /* pointer into target list of switch instr. */
-    classinfo *cls;                                       /* temporary */
     bool maythrow;               /* true if this instruction may throw */
-    classinfo *myclass;
        unresolved_field *uf;                        /* for field accesses */
-       fieldinfo **fieldinfop;                      /* for field accesses */
+       constant_FMIref *fieldref;                   /* for field accesses */
        s4 i;
-       s4 b_index;
        typecheck_result r;
-
-       LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->debug_nr);
+       resolve_result_t result;
+       branch_target_t *table;
+       lookup_target_t *lookup;
+       jitdata *jd = state->jd;
+       varinfo *dv;
+       exceptiontable *ex;
+
+       LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
        LOGFLUSH;
+       DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
 
        superblockend = false;
        state->bptr->flags = BBFINISHED;
-       b_index = state->bptr - state->m->basicblocks;
-
-       /* init stack at the start of this block */
-       state->curstack = state->bptr->instack;
 
        /* prevent compiler warnings */
 
-       dst = NULL;
+       dv = NULL;
 
        /* determine the active exception handlers for this block */
        /* XXX could use a faster algorithm with sorted lists or  */
        /* something?                                             */
        len = 0;
-       for (i = 0; i < state->cd->exceptiontablelength; ++i) {
-               if ((state->cd->exceptiontable[i].start <= state->bptr) && (state->cd->exceptiontable[i].end > state->bptr)) {
-                       LOG1("active handler L%03d", state->cd->exceptiontable[i].handler->debug_nr);
-                       state->handlers[len++] = state->cd->exceptiontable + i;
+       for (ex = state->cd->exceptiontable; ex ; ex = ex->down) {
+               if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
+                       LOG1("active handler L%03d", ex->handler->nr);
+                       state->handlers[len++] = ex;
                }
        }
        state->handlers[len] = NULL;
 
        /* init variable types at the start of this block */
-       typevectorset_copy_inplace(MGET_TYPEVECTOR(state->localbuf,b_index,state->numlocals),
-                       state->localset,state->numlocals);
-
-       /* XXX FIXME FOR INLINING */
-       if (!useinlining) {
-               if (state->handlers[0])
-                       for (i=0; i<state->numlocals; ++i)
-                               if (state->localset->td[i].type == TYPE_ADR
-                                               && TYPEINFO_IS_NEWOBJECT(state->localset->td[i].info)) {
-                                       /* XXX we do not check this for the uninitialized 'this' instance in */
-                                       /* <init> methods. Otherwise there are problems with try blocks in   */
-                                       /* <init>. The spec seems to indicate that we should perform the test*/
-                                       /* in all cases, but this fails with real code.                      */
-                                       /* Example: org/eclipse/ui/internal/PerspectiveBarNewContributionItem*/
-                                       /* 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);
-                                               TYPECHECK_VERIFYERROR_bool("Uninitialized object in local variable inside try block");
-                                       }
-                               }
-       }
-       DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
+       typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
+
+       DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars, 
+                               state->bptr->indepth));
+       DOLOG(typevector_print(stdout, jd->var, state->numlocals));
        LOGNL; LOGFLUSH;
 
        /* loop over the instructions */
@@ -1580,14 +1410,14 @@ verify_basic_block(verifier_state *state)
        while (--len >= 0)  {
                TYPECHECK_COUNT(stat_ins);
 
-               DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
-               LOGNL; LOGFLUSH;
+               iptr = state->iptr;
 
-               DOLOG(show_icmd(state->iptr,false)); LOGNL; LOGFLUSH;
+               DOLOG(typevector_print(stdout, jd->var, state->numlocals));
+               LOGNL; LOGFLUSH;
+               DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); LOGNL; LOGFLUSH;
 
-               opcode = state->iptr->opc;
-               myclass = state->iptr->method->class;
-               dst = state->iptr->dst;
+               opcode = iptr->opc;
+               dv = VAROP(iptr->dst);
                maythrow = false;
 
                switch (opcode) {
@@ -1598,86 +1428,53 @@ verify_basic_block(verifier_state *state)
                        /* We just need to copy the typeinfo */
                        /* for slots containing addresses.   */
 
-                       /* CAUTION: We assume that the destination stack
-                        * slots were continuously allocated in
-                        * memory!  (The current implementation in
-                        * stack.c)
-                        */
-
-                       case ICMD_DUP:
-                               TYPECHECK_COUNT(stat_ins_stack);
-                               COPYTYPE(state->curstack,dst);
-                               break;
-
-                       case ICMD_DUP_X1:
-                               TYPECHECK_COUNT(stat_ins_stack);
-                               COPYTYPE(state->curstack,dst);
-                               COPYTYPE(state->curstack,dst-2);
-                               COPYTYPE(state->curstack->prev,dst-1);
-                               break;
-
-                       case ICMD_DUP_X2:
-                               TYPECHECK_COUNT(stat_ins_stack);
-                               COPYTYPE(state->curstack,dst);
-                               COPYTYPE(state->curstack,dst-3);
-                               COPYTYPE(state->curstack->prev,dst-1);
-                               COPYTYPE(state->curstack->prev->prev,dst-2);
-                               break;
-
-                       case ICMD_DUP2:
-                               TYPECHECK_COUNT(stat_ins_stack);
-                               COPYTYPE(state->curstack,dst);
-                               COPYTYPE(state->curstack->prev,dst-1);
-                               break;
-
-                       case ICMD_DUP2_X1:
-                               TYPECHECK_COUNT(stat_ins_stack);
-                               COPYTYPE(state->curstack,dst);
-                               COPYTYPE(state->curstack->prev,dst-1);
-                               COPYTYPE(state->curstack,dst-3);
-                               COPYTYPE(state->curstack->prev,dst-4);
-                               COPYTYPE(state->curstack->prev->prev,dst-2);
-                               break;
-
-                       case ICMD_DUP2_X2:
-                               TYPECHECK_COUNT(stat_ins_stack);
-                               COPYTYPE(state->curstack,dst);
-                               COPYTYPE(state->curstack->prev,dst-1);
-                               COPYTYPE(state->curstack,dst-4);
-                               COPYTYPE(state->curstack->prev,dst-5);
-                               COPYTYPE(state->curstack->prev->prev,dst-2);
-                               COPYTYPE(state->curstack->prev->prev->prev,dst-3);
-                               break;
-
-                       case ICMD_SWAP:
+                       case ICMD_MOVE:
+                       case ICMD_COPY:
                                TYPECHECK_COUNT(stat_ins_stack);
-                               COPYTYPE(state->curstack,dst-1);
-                               COPYTYPE(state->curstack->prev,dst);
+                               COPYTYPE(iptr->s1, iptr->dst);
+                               dv->type = VAROP(iptr->s1)->type;
                                break;
 
                                /****************************************/
                                /* PRIMITIVE VARIABLE ACCESS            */
 
-                       case ICMD_ILOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_INT)) 
+                       case ICMD_ILOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_INT)) 
                                                                 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        dv->type = TYPE_INT;
                                                         break;
-                       case ICMD_IINC:  if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_INT))
+                       case ICMD_IINC:  if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_INT))
                                                                 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        dv->type = TYPE_INT;
                                                         break;
-                       case ICMD_FLOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_FLOAT))
+                       case ICMD_FLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_FLT))
                                                                 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        dv->type = TYPE_FLT;
                                                         break;
-                       case ICMD_LLOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_LONG))
+                       case ICMD_LLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_LNG))
                                                                 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        dv->type = TYPE_LNG;
                                                         break;
-                       case ICMD_DLOAD: if (!typevectorset_checktype(state->localset,state->iptr->op1,TYPE_DOUBLE))
+                       case ICMD_DLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_DBL))
                                                                 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
+                                                        dv->type = TYPE_DBL;
                                                         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;
+                       case ICMD_ISTORE: 
+                                                        typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
+                                                        typevector_store(jd->var,state->iptr->dst.varindex,TYPE_INT,NULL); 
+                                                        break;
+                       case ICMD_FSTORE: 
+                                                        typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
+                                                        typevector_store(jd->var,state->iptr->dst.varindex,TYPE_FLT,NULL); 
+                                                        break;
+                       case ICMD_LSTORE: 
+                                                        typecheck_invalidate_locals(state, state->iptr->dst.varindex, true);
+                                                        typevector_store(jd->var,state->iptr->dst.varindex,TYPE_LNG,NULL); 
+                                                        break;
+                       case ICMD_DSTORE: 
+                                                        typecheck_invalidate_locals(state, state->iptr->dst.varindex, true);
+                                                        typevector_store(jd->var,state->iptr->dst.varindex,TYPE_DBL,NULL); 
+                                                        break;
 
                                /****************************************/
                                /* LOADING ADDRESS FROM VARIABLE        */
@@ -1686,35 +1483,25 @@ verify_basic_block(verifier_state *state)
                                TYPECHECK_COUNT(stat_ins_aload);
 
                                /* loading a returnAddress is not allowed */
-                               if (state->jsrencountered) {
-                                       if (!typevectorset_checkreference(state->localset,state->iptr->op1)) {
-                                               TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
-                                       }
-                                       if (typevectorset_copymergedtype(state->m,state->localset,state->iptr->op1,&(dst->typeinfo)) == -1)
-                                               return false;
-                               }
-                               else {
-                                       if (!TYPEDESC_IS_REFERENCE(state->localset->td[state->iptr->op1])) {
-                                               TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
-                                       }
-                                       TYPEINFO_COPY(state->localset->td[state->iptr->op1].info,dst->typeinfo);
+                               if (!TYPEDESC_IS_REFERENCE(*VAROP(state->iptr->s1))) {
+                                       TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
                                }
+                               TYPEINFO_COPY(VAROP(state->iptr->s1)->typeinfo,dv->typeinfo);
+                               dv->type = TYPE_ADR;
                                break;
 
                                /****************************************/
                                /* STORING ADDRESS TO VARIABLE          */
 
                        case ICMD_ASTORE:
-                               if (state->handlers[0] && TYPEINFO_IS_NEWOBJECT(state->curstack->typeinfo)) {
-                                       TYPECHECK_VERIFYERROR_bool("Storing uninitialized object in local variable inside try block");
-                               }
+                               typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
 
-                               if (TYPESTACK_IS_RETURNADDRESS(state->curstack)) {
-                                       typevectorset_store_retaddr(state->localset,state->iptr->op1,&(state->curstack->typeinfo));
+                               if (TYPEINFO_IS_PRIMITIVE(VAROP(state->iptr->s1)->typeinfo)) {
+                                       typevector_store_retaddr(jd->var,state->iptr->dst.varindex,&(VAROP(state->iptr->s1)->typeinfo));
                                }
                                else {
-                                       typevectorset_store(state->localset,state->iptr->op1,TYPE_ADDRESS,
-                                                       &(state->curstack->typeinfo));
+                                       typevector_store(jd->var,state->iptr->dst.varindex,TYPE_ADR,
+                                                       &(VAROP(state->iptr->s1)->typeinfo));
                                }
                                break;
 
@@ -1722,148 +1509,246 @@ verify_basic_block(verifier_state *state)
                                /* LOADING ADDRESS FROM ARRAY           */
 
                        case ICMD_AALOAD:
-                               if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->typeinfo))
+                               if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(VAROP(state->iptr->s1)->typeinfo))
                                        TYPECHECK_VERIFYERROR_bool("illegal instruction: AALOAD on non-reference array");
 
-                               if (!typeinfo_init_component(&state->curstack->prev->typeinfo,&dst->typeinfo))
+                               if (!typeinfo_init_component(&VAROP(state->iptr->s1)->typeinfo,&dv->typeinfo))
                                        return false;
+                               dv->type = TYPE_ADR;
                                maythrow = true;
                                break;
 
                                /****************************************/
                                /* FIELD ACCESS                         */
 
+                       case ICMD_PUTFIELD:
+                       case ICMD_PUTSTATIC:
                        case ICMD_PUTFIELDCONST:
                        case ICMD_PUTSTATICCONST:
-                               TYPECHECK_COUNT(stat_ins_field);
+                       case ICMD_GETFIELD:
+                       case ICMD_GETSTATIC:
+                               {
+                                       varinfo *valueslot = NULL;
+                                       typeinfo *instanceti = NULL;
+                                       typeinfo *valueti = NULL;
+                                       bool isstatic = false;
+                                       bool isput = false;
+                                       typeinfo constti;
+
+                                       TYPECHECK_COUNT(stat_ins_field);
+
+                                       if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
+                                               uf = state->iptr->sx.s23.s3.uf;
+                                               fieldref = uf->fieldref;
+                                       }
+                                       else {
+                                               uf = NULL;
+                                               fieldref = state->iptr->sx.s23.s3.fmiref;
+                                       }
+
+                                       /* get opcode dependent values */
+
+                                       switch (state->iptr->opc) {
+                                               case ICMD_PUTFIELD:
+                                                       isput = true;
+                                                       valueslot = VAROP(state->iptr->sx.s23.s2);
+                                                       instanceti = &(VAROP(state->iptr->s1)->typeinfo);
+                                                       break;
+
+                                               case ICMD_PUTFIELDCONST:
+                                                       isput = true;
+                                                       instanceti = &(VAROP(state->iptr->s1)->typeinfo);
+putfield_const_tail:
+                                                       if (IS_ADR_TYPE(fieldref->parseddesc.fd->type)) {
+                                                               /* XXX check for java.lang.Class constant values? */
+                                                               if (state->iptr->sx.val.anyptr) {
+                                                                       assert(class_java_lang_String);
+                                                                       assert(class_java_lang_String->state & CLASS_LOADED);
+                                                                       assert(class_java_lang_String->state & CLASS_LINKED);
+                                                                       typeinfo_init_classinfo(&constti, class_java_lang_String);
+                                                               }
+                                                               else {
+                                                                       TYPEINFO_INIT_NULLTYPE(constti);
+                                                               }
+                                                               valueti = &constti;
+                                                       }
+                                                       break;
+
+                                               case ICMD_PUTSTATIC:
+                                                       isput = true;
+                                                       isstatic = true;
+                                                       valueslot = VAROP(state->iptr->s1);
+                                                       break;
+
+                                               case ICMD_PUTSTATICCONST:
+                                                       isput = true;
+                                                       isstatic = true;
+                                                       goto putfield_const_tail;
+
+                                               case ICMD_GETFIELD:
+                                                       instanceti = &(VAROP(state->iptr->s1)->typeinfo);
+                                                       break;
+
+                                               case ICMD_GETSTATIC:
+                                                       isstatic = true;
+                                                       break;
+
+                                               default:
+                                                       assert(false);
+                                       }
 
-                               uf = INSTRUCTION_PUTCONST_FIELDREF(state->iptr);
-                               fieldinfop = INSTRUCTION_PUTCONST_FIELDINFO_PTR(state->iptr);
+                                       if (valueslot && IS_ADR_TYPE(valueslot->type)) {
+                                               valueti = &(valueslot->typeinfo);
+                                       }
 
-                               goto fieldaccess_tail;
+                                       /* try to resolve the field reference lazily */
 
-                       case ICMD_PUTFIELD:
-                       case ICMD_PUTSTATIC:
-                               TYPECHECK_COUNT(stat_ins_field);
+                                       result = resolve_field_lazy(state->m, fieldref);
 
-                               uf = (unresolved_field *) state->iptr[0].target;
-                               fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
-                               
-                               goto fieldaccess_tail;
+                                       if (result == resolveSucceeded) {
+                                               fieldinfo *fi;
 
-                       case ICMD_GETFIELD:
-                       case ICMD_GETSTATIC:
-                               TYPECHECK_COUNT(stat_ins_field);
+                                               /* perform verification checks now */
+
+                                               fi  = fieldref->p.field;
 
-                               uf = (unresolved_field *) state->iptr[0].target;
-                               fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
+                                               result = resolve_field_verifier_checks(
+                                                               state->m, fieldref, fi->class, fi,
+                                                               instanceti, valueti, isstatic, isput);
+                                       }
 
-                               /* the result is pushed on the stack */
-                               if (dst->type == TYPE_ADR) {
-                                       if (!typeinfo_init_from_typedesc(uf->fieldref->parseddesc.fd,NULL,&(dst->typeinfo)))
+                                       if (result == resolveFailed)
                                                return false;
-                               }
 
-fieldaccess_tail:
-                               /* record the subtype constraints for this field access */
-                               if (!constrain_unresolved_field(uf,state->m->class,state->m,state->iptr,state->curstack))
-                                       return false; /* XXX maybe wrap exception? */
+                                       /* if not resolved, yet, create an unresolved field */
 
-                               /* try to resolve the field reference */
-                               if (!resolve_field(uf,resolveLazy,fieldinfop))
-                                       return false;
+                                       if (result != resolveSucceeded) {
+                                               if (!uf) {
+                                                       uf = resolve_create_unresolved_field(state->m->class, 
+                                                                       state->m, state->iptr);
+                                                       if (!uf)
+                                                               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);
-                                       
-                               maythrow = true;
+                                                       state->iptr->sx.s23.s3.uf = uf;
+                                                       state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+                                               }
+
+                                               /* record the subtype constraints for this field access */
+
+                                               if (!resolve_constrain_unresolved_field(
+                                                                       uf, state->m->class, state->m,
+                                                                       instanceti, valueti))
+                                                       return false; /* XXX maybe wrap exception? */
+
+                                               TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
+                                               TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) && 
+                                                               !state->iptr->sx.s23.s3.fmiref->p.field->class->initialized,
+                                                               stat_ins_field_uninitialized);
+                                       }
+                                               
+                                       /* write the result type */
+
+                                       if (iptr->opc == ICMD_GETFIELD || iptr->opc == ICMD_GETSTATIC) {
+                                               dv->type = fieldref->parseddesc.fd->type;
+                                               if (dv->type == TYPE_ADR) {
+                                                       if (!typeinfo_init_from_typedesc(fieldref->parseddesc.fd, 
+                                                                               NULL, &(dv->typeinfo)))
+                                                               return false;
+                                               }
+                                       }
+
+                                       maythrow = true;
+                               }
                                break;
 
                                /****************************************/
                                /* PRIMITIVE ARRAY ACCESS               */
 
                        case ICMD_ARRAYLENGTH:
-                               if (!TYPEINFO_MAYBE_ARRAY(state->curstack->typeinfo)
-                                               && state->curstack->typeinfo.typeclass.cls != pseudo_class_Arraystub)
+                               if (!TYPEINFO_MAYBE_ARRAY(VAROP(state->iptr->s1)->typeinfo)
+                                               && VAROP(state->iptr->s1)->typeinfo.typeclass.cls != pseudo_class_Arraystub)
                                        TYPECHECK_VERIFYERROR_bool("illegal instruction: ARRAYLENGTH on non-array");
+                               dv->type = TYPE_INT;
                                maythrow = true;
                                break;
 
                        case ICMD_BALOAD:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
-                                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BYTE))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BOOLEAN)
+                                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BYTE))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
+                               dv->type = TYPE_INT;
                                maythrow = true;
                                break;
                        case ICMD_CALOAD:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_CHAR))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_CHAR))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
+                               dv->type = TYPE_INT;
                                maythrow = true;
                                break;
                        case ICMD_DALOAD:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_DOUBLE))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
+                               dv->type = TYPE_DBL;
                                maythrow = true;
                                break;
                        case ICMD_FALOAD:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_FLOAT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
+                               dv->type = TYPE_FLT;
                                maythrow = true;
                                break;
                        case ICMD_IALOAD:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_INT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_INT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
+                               dv->type = TYPE_INT;
                                maythrow = true;
                                break;
                        case ICMD_SALOAD:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_SHORT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_SHORT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
+                               dv->type = TYPE_INT;
                                maythrow = true;
                                break;
                        case ICMD_LALOAD:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_LONG))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_LONG))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
+                               dv->type = TYPE_LNG;
                                maythrow = true;
                                break;
 
                        case ICMD_BASTORE:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
-                                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BOOLEAN)
+                                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BYTE))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
                        case ICMD_CASTORE:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_CHAR))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
                        case ICMD_DASTORE:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_DOUBLE))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
                        case ICMD_FASTORE:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_FLOAT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
                        case ICMD_IASTORE:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_INT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
                        case ICMD_SASTORE:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_SHORT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
                        case ICMD_LASTORE:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_LONG))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
@@ -1873,41 +1758,41 @@ fieldaccess_tail:
                                /* destination is an array of references. Assignability to    */
                                /* the actual array must be checked at runtime, each time the */
                                /* instruction is performed. (See builtin_canstore.)          */
-                               TYPECHECK_ADR(state->curstack);
-                               TYPECHECK_INT(state->curstack->prev);
-                               TYPECHECK_ADR(state->curstack->prev->prev);
-                               if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->prev->typeinfo))
+                               TYPECHECK_ADR_OP(state->iptr->sx.s23.s3);
+                               TYPECHECK_INT_OP(state->iptr->sx.s23.s2);
+                               TYPECHECK_ADR_OP(state->iptr->s1);
+                               if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(VAROP(state->iptr->s1)->typeinfo))
                                        TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
                                maythrow = true;
                                break;
 
                        case ICMD_IASTORECONST:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_INT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_INT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
 
                        case ICMD_LASTORECONST:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_LONG))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_LONG))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
 
                        case ICMD_BASTORECONST:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BOOLEAN)
-                                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BYTE))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_BOOLEAN)
+                                               && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_BYTE))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
 
                        case ICMD_CASTORECONST:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_CHAR))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_CHAR))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
 
                        case ICMD_SASTORECONST:
-                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_SHORT))
+                               if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_SHORT))
                                        TYPECHECK_VERIFYERROR_bool("Array type mismatch");
                                maythrow = true;
                                break;
@@ -1916,48 +1801,50 @@ fieldaccess_tail:
                                /* ADDRESS CONSTANTS                    */
 
                        case ICMD_ACONST:
-                               if (state->iptr->target) {
+                               if (state->iptr->flags.bits & INS_FLAG_CLASS) {
                                        /* a java.lang.Class reference */
-                                       TYPEINFO_INIT_JAVA_LANG_CLASS(dst->typeinfo,(constant_classref *)state->iptr->target);
+                                       TYPEINFO_INIT_JAVA_LANG_CLASS(dv->typeinfo,state->iptr->sx.val.c);
                                }
                                else {
-                                       if (state->iptr->val.a == NULL)
-                                               TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
+                                       if (state->iptr->sx.val.anyptr == NULL)
+                                               TYPEINFO_INIT_NULLTYPE(dv->typeinfo);
                                        else {
                                                /* string constant (or constant for builtin function) */
-                                               typeinfo_init_classinfo(&(dst->typeinfo),class_java_lang_String);
+                                               typeinfo_init_classinfo(&(dv->typeinfo),class_java_lang_String);
                                        }
                                }
+                               dv->type = TYPE_ADR;
                                break;
 
                                /****************************************/
                                /* CHECKCAST AND INSTANCEOF             */
 
                        case ICMD_CHECKCAST:
-                               TYPECHECK_ADR(state->curstack);
+                               TYPECHECK_ADR_OP(state->iptr->s1);
                                /* returnAddress is not allowed */
-                               if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
+                               if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
                                        TYPECHECK_VERIFYERROR_bool("Illegal instruction: CHECKCAST on non-reference");
 
-                               cls = (classinfo *) state->iptr[0].val.a;
-                               if (cls)
-                                       typeinfo_init_classinfo(&(dst->typeinfo),cls);
-                               else
-                                       if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
+                               if (!typeinfo_init_class(&(dv->typeinfo),state->iptr->sx.s23.s3.c))
                                                return false;
+                               dv->type = TYPE_ADR;
                                maythrow = true;
                                break;
 
                        case ICMD_INSTANCEOF:
-                               TYPECHECK_ADR(state->curstack);
+                               TYPECHECK_ADR_OP(state->iptr->s1);
                                /* returnAddress is not allowed */
-                               if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
+                               if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
                                        TYPECHECK_VERIFYERROR_bool("Illegal instruction: INSTANCEOF on non-reference");
+                               dv->type = TYPE_INT;
                                break;
 
                                /****************************************/
                                /* BRANCH INSTRUCTIONS                  */
 
+                       case ICMD_INLINE_GOTO:
+                               COPYTYPE(state->iptr->s1,state->iptr->dst);
+                               /* FALLTHROUGH! */
                        case ICMD_GOTO:
                                superblockend = true;
                                /* FALLTHROUGH! */
@@ -1977,23 +1864,52 @@ fieldaccess_tail:
                        case ICMD_IF_ICMPLE:
                        case ICMD_IF_ACMPEQ:
                        case ICMD_IF_ACMPNE:
+
                        case ICMD_IF_LEQ:
                        case ICMD_IF_LNE:
                        case ICMD_IF_LLT:
                        case ICMD_IF_LGE:
                        case ICMD_IF_LGT:
                        case ICMD_IF_LLE:
+
                        case ICMD_IF_LCMPEQ:
                        case ICMD_IF_LCMPNE:
                        case ICMD_IF_LCMPLT:
                        case ICMD_IF_LCMPGE:
                        case ICMD_IF_LCMPGT:
                        case ICMD_IF_LCMPLE:
+
+                       case ICMD_IF_FCMPEQ:
+                       case ICMD_IF_FCMPNE:
+
+                       case ICMD_IF_FCMPL_LT:
+                       case ICMD_IF_FCMPL_GE:
+                       case ICMD_IF_FCMPL_GT:
+                       case ICMD_IF_FCMPL_LE:
+
+                       case ICMD_IF_FCMPG_LT:
+                       case ICMD_IF_FCMPG_GE:
+                       case ICMD_IF_FCMPG_GT:
+                       case ICMD_IF_FCMPG_LE:
+
+                       case ICMD_IF_DCMPEQ:
+                       case ICMD_IF_DCMPNE:
+
+                       case ICMD_IF_DCMPL_LT:
+                       case ICMD_IF_DCMPL_GE:
+                       case ICMD_IF_DCMPL_GT:
+                       case ICMD_IF_DCMPL_LE:
+
+                       case ICMD_IF_DCMPG_LT:
+                       case ICMD_IF_DCMPG_GE:
+                       case ICMD_IF_DCMPG_GT:
+                       case ICMD_IF_DCMPG_LE:
                                TYPECHECK_COUNT(stat_ins_branch);
-                               tbptr = (basicblock *) state->iptr->target;
 
                                /* propagate stack and variables to the target block */
-                               if (!typestate_reach(state,tbptr,dst,state->localset))
+                               if (!typestate_reach(state, state->iptr->dst.block,
+                                                                        state->bptr->outvars, jd->var, 
+                                                                        state->bptr->outdepth))
                                        return false;
                                break;
 
@@ -2002,40 +1918,53 @@ fieldaccess_tail:
 
                        case ICMD_TABLESWITCH:
                                TYPECHECK_COUNT(stat_ins_switch);
-                               {
-                                       s4 *s4ptr = state->iptr->val.a;
-                                       s4ptr++;              /* skip default */
-                                       i = *s4ptr++;         /* low */
-                                       i = *s4ptr++ - i + 2; /* +1 for default target */
+
+                               table = iptr->dst.table;
+                               i = iptr->sx.s23.s3.tablehigh
+                                       - iptr->sx.s23.s2.tablelow + 1 + 1; /* plus default */
+
+                               while (--i >= 0) {
+                                       tbptr = (table++)->block;
+                                       LOG2("target %d is block %04d",i,tbptr->nr);
+                                       if (!typestate_reach(state, tbptr, state->bptr->outvars,
+                                                                                jd->var, state->bptr->outdepth))
+                                               return false;
                                }
-                               goto switch_instruction_tail;
+
+                               LOG("switch done");
+                               superblockend = true;
+                               break;
 
                        case ICMD_LOOKUPSWITCH:
                                TYPECHECK_COUNT(stat_ins_switch);
-                               {
-                                       s4 *s4ptr = state->iptr->val.a;
-                                       s4ptr++;              /* skip default */
-                                       i = *s4ptr++ + 1;     /* count +1 for default */
-                               }
-switch_instruction_tail:
-                               tptr = (basicblock **)state->iptr->target;
+
+                               lookup = iptr->dst.lookup;
+                               i = iptr->sx.s23.s2.lookupcount;
+
+                               if (!typestate_reach(state,iptr->sx.s23.s3.lookupdefault.block,
+                                                                        state->bptr->outvars, jd->var,
+                                                                        state->bptr->outdepth))
+                                       return false;
 
                                while (--i >= 0) {
-                                       tbptr = *tptr++;
-                                       LOG2("target %d is block %04d",(tptr-(basicblock **)state->iptr->target)-1,tbptr->debug_nr);
-                                       if (!typestate_reach(state,tbptr,dst,state->localset))
+                                       tbptr = (lookup++)->target.block;
+                                       LOG2("target %d is block %04d",i,tbptr->nr);
+                                       if (!typestate_reach(state, tbptr, state->bptr->outvars,
+                                                               jd->var, state->bptr->outdepth))
                                                return false;
                                }
+
                                LOG("switch done");
                                superblockend = true;
                                break;
 
+
                                /****************************************/
                                /* ADDRESS RETURNS AND THROW            */
 
                        case ICMD_ATHROW:
                                TYPECHECK_COUNT(stat_ins_athrow);
-                               r = typeinfo_is_assignable_to_class(&state->curstack->typeinfo,
+                               r = typeinfo_is_assignable_to_class(&VAROP(state->iptr->s1)->typeinfo,
                                                CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
                                if (r == typecheck_FALSE)
                                        TYPECHECK_VERIFYERROR_bool("illegal instruction: ATHROW on non-Throwable");
@@ -2044,12 +1973,13 @@ switch_instruction_tail:
                                if (r == typecheck_MAYBE) {
                                        /* the check has to be postponed. we need a patcher */
                                        TYPECHECK_COUNT(stat_ins_athrow_unresolved);
-                                       state->iptr->val.a = create_unresolved_class(
+                                       iptr->sx.s23.s2.uc = create_unresolved_class(
                                                        state->m, 
                                                        /* XXX make this more efficient, use class_java_lang_Throwable
                                                         * directly */
                                                        class_get_classref(state->m->class,utf_java_lang_Throwable),
-                                                       &state->curstack->typeinfo);
+                                                       &VAROP(state->iptr->s1)->typeinfo);
+                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
                                }
                                superblockend = true;
                                maythrow = true;
@@ -2057,11 +1987,11 @@ switch_instruction_tail:
 
                        case ICMD_ARETURN:
                                TYPECHECK_COUNT(stat_ins_areturn);
-                               if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
+                               if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
                                        TYPECHECK_VERIFYERROR_bool("illegal instruction: ARETURN on non-reference");
 
-                               if (state->returntype.type != TYPE_ADDRESS
-                                               || (r = typeinfo_is_assignable(&state->curstack->typeinfo,&(state->returntype.info))) 
+                               if (state->returntype.type != TYPE_ADR
+                                               || (r = typeinfo_is_assignable(&VAROP(state->iptr->s1)->typeinfo,&(state->returntype.typeinfo))) 
                                                                == typecheck_FALSE)
                                        TYPECHECK_VERIFYERROR_bool("Return type mismatch");
                                if (r == typecheck_FAIL)
@@ -2069,10 +1999,11 @@ switch_instruction_tail:
                                if (r == typecheck_MAYBE) {
                                        /* the check has to be postponed, we need a patcher */
                                        TYPECHECK_COUNT(stat_ins_areturn_unresolved);
-                                       state->iptr->val.a = create_unresolved_class(
+                                       iptr->sx.s23.s2.uc = create_unresolved_class(
                                                        state->m, 
                                                        state->m->parseddesc->returntype.classref,
-                                                       &state->curstack->typeinfo);
+                                                       &VAROP(state->iptr->s1)->typeinfo);
+                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
                                }
                                goto return_tail;
 
@@ -2084,15 +2015,15 @@ switch_instruction_tail:
                                goto return_tail;
 
                        case ICMD_LRETURN:
-                               if (state->returntype.type != TYPE_LONG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
+                               if (state->returntype.type != TYPE_LNG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
                                goto return_tail;
 
                        case ICMD_FRETURN:
-                               if (state->returntype.type != TYPE_FLOAT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
+                               if (state->returntype.type != TYPE_FLT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
                                goto return_tail;
 
                        case ICMD_DRETURN:
-                               if (state->returntype.type != TYPE_DOUBLE) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
+                               if (state->returntype.type != TYPE_DBL) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
                                goto return_tail;
 
                        case ICMD_RETURN:
@@ -2103,7 +2034,7 @@ return_tail:
                                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))
+                                       if (!typevector_checktype(jd->var,state->numlocals-1,TYPE_INT))
                                                TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'");
                                }
 
@@ -2116,19 +2047,11 @@ return_tail:
 
                        case ICMD_JSR:
                                LOG("jsr");
-                               state->jsrencountered = true;
 
-                               /* This is a dirty hack. It is needed
-                                * because of the special handling of
-                                * ICMD_JSR in stack.c
-                                */
-                               dst = (stackptr) state->iptr->val.a;
-
-                               tbptr = (basicblock *) state->iptr->target;
-                               if (state->bptr + 1 == (state->m->basicblocks + state->m->basicblockcount + 1))
-                                       TYPECHECK_VERIFYERROR_bool("Illegal instruction: JSR at end of bytecode");
-                               typestack_put_retaddr(dst,state->bptr+1,state->localset);
-                               if (!typestate_reach(state,tbptr,dst,state->localset))
+                               tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
+                               TYPEINFO_INIT_RETURNADDRESS(dv->typeinfo, state->bptr->next);
+                               if (!typestate_reach(state, tbptr, state->bptr->outvars, jd->var,
+                                                       state->bptr->outdepth))
                                        return false;
 
                                superblockend = true;
@@ -2136,10 +2059,11 @@ return_tail:
 
                        case ICMD_RET:
                                /* check returnAddress variable */
-                               if (!typevectorset_checkretaddr(state->localset,state->iptr->op1))
+                               if (!typevector_checkretaddr(jd->var,state->iptr->s1.varindex))
                                        TYPECHECK_VERIFYERROR_bool("illegal instruction: RET using non-returnAddress variable");
 
-                               if (!typestate_ret(state,state->iptr->op1))
+                               if (!typestate_reach(state, iptr->dst.block, state->bptr->outvars, jd->var,
+                                                       state->bptr->outdepth))
                                        return false;
 
                                superblockend = true;
@@ -2155,7 +2079,7 @@ return_tail:
                                TYPECHECK_COUNT(stat_ins_invoke);
                                if (!verify_invocation(state))
                                        return false;
-                               TYPECHECK_COUNTIF(!state->iptr[0].val.a,stat_ins_invoke_unresolved);
+                               TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(iptr), stat_ins_invoke_unresolved);
                                maythrow = true;
                                break;
 
@@ -2201,13 +2125,6 @@ return_tail:
                                LOG("Should have been converted to builtin function call.");
                                TYPECHECK_ASSERT(false);
                                break;
-
-                       case ICMD_READONLY_ARG:
-                       case ICMD_CLEAR_ARGREN:
-                               LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
-                               LOG("Should have been replaced in stack.c.");
-                               TYPECHECK_ASSERT(false);
-                               break;
 #endif
 
                                /****************************************/
@@ -2217,7 +2134,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.)
@@ -2227,31 +2146,23 @@ return_tail:
 
                        case ICMD_IDIV:
                        case ICMD_IREM:
+                               dv->type = TYPE_INT;
+                               maythrow = true;
+                               break;
+
                        case ICMD_LDIV:
                        case ICMD_LREM:
-
+                               dv->type = TYPE_LNG;
                                maythrow = true;
                                break;
 
                                /* Instructions which never throw a runtime exception: */
-#if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
                        case ICMD_NOP:
                        case ICMD_POP:
                        case ICMD_POP2:
+                               break;
 
                        case ICMD_ICONST:
-                       case ICMD_LCONST:
-                       case ICMD_FCONST:
-                       case ICMD_DCONST:
-
-                       case ICMD_IFEQ_ICONST:
-                       case ICMD_IFNE_ICONST:
-                       case ICMD_IFLT_ICONST:
-                       case ICMD_IFGE_ICONST:
-                       case ICMD_IFGT_ICONST:
-                       case ICMD_IFLE_ICONST:
-                       case ICMD_ELSE_ICONST:
-
                        case ICMD_IADD:
                        case ICMD_ISUB:
                        case ICMD_IMUL:
@@ -2262,24 +2173,8 @@ return_tail:
                        case ICMD_ISHL:
                        case ICMD_ISHR:
                        case ICMD_IUSHR:
-                       case ICMD_LADD:
-                       case ICMD_LSUB:
-                       case ICMD_LMUL:
-                       case ICMD_LNEG:
-                       case ICMD_LAND:
-                       case ICMD_LOR:
-                       case ICMD_LXOR:
-                       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:
-                       case ICMD_LDIVPOW2:
                        case ICMD_IADDCONST:
                        case ICMD_ISUBCONST:
                        case ICMD_IMULCONST:
@@ -2290,6 +2185,34 @@ return_tail:
                        case ICMD_ISHRCONST:
                        case ICMD_IUSHRCONST:
                        case ICMD_IREMPOW2:
+                       case ICMD_INT2BYTE:
+                       case ICMD_INT2CHAR:
+                       case ICMD_INT2SHORT:
+                       case ICMD_L2I:
+                       case ICMD_F2I:
+                       case ICMD_D2I:
+                       case ICMD_LCMP:
+                       case ICMD_LCMPCONST:
+                       case ICMD_FCMPL:
+                       case ICMD_FCMPG:
+                       case ICMD_DCMPL:
+                       case ICMD_DCMPG:
+                               dv->type = TYPE_INT;
+                               break;
+
+                       case ICMD_LCONST:
+                       case ICMD_LADD:
+                       case ICMD_LSUB:
+                       case ICMD_LMUL:
+                       case ICMD_LNEG:
+                       case ICMD_LAND:
+                       case ICMD_LOR:
+                       case ICMD_LXOR:
+                       case ICMD_LSHL:
+                       case ICMD_LSHR:
+                       case ICMD_LUSHR:
+                       case ICMD_LMULPOW2:
+                       case ICMD_LDIVPOW2:
                        case ICMD_LADDCONST:
                        case ICMD_LSUBCONST:
                        case ICMD_LMULCONST:
@@ -2300,45 +2223,43 @@ return_tail:
                        case ICMD_LSHRCONST:
                        case ICMD_LUSHRCONST:
                        case ICMD_LREMPOW2:
-
                        case ICMD_I2L:
-                       case ICMD_I2F:
-                       case ICMD_I2D:
-                       case ICMD_L2I:
-                       case ICMD_L2F:
-                       case ICMD_L2D:
-                       case ICMD_F2I:
                        case ICMD_F2L:
-                       case ICMD_F2D:
-                       case ICMD_D2I:
                        case ICMD_D2L:
-                       case ICMD_D2F:
-                       case ICMD_INT2BYTE:
-                       case ICMD_INT2CHAR:
-                       case ICMD_INT2SHORT:
-
-                       case ICMD_LCMP:
-                       case ICMD_LCMPCONST:
-                       case ICMD_FCMPL:
-                       case ICMD_FCMPG:
-                       case ICMD_DCMPL:
-                       case ICMD_DCMPG:
+                               dv->type = TYPE_LNG;
+                               break;
 
+                       case ICMD_FCONST:
+                       case ICMD_I2F:
+                       case ICMD_L2F:
+                       case ICMD_D2F:
                        case ICMD_FADD:
-                       case ICMD_DADD:
                        case ICMD_FSUB:
-                       case ICMD_DSUB:
                        case ICMD_FMUL:
-                       case ICMD_DMUL:
                        case ICMD_FDIV:
-                       case ICMD_DDIV:
                        case ICMD_FREM:
-                       case ICMD_DREM:
                        case ICMD_FNEG:
+                               dv->type = TYPE_FLT;
+                               break;
+
+                       case ICMD_DCONST:
+                       case ICMD_I2D:
+                       case ICMD_L2D:
+                       case ICMD_F2D:
+                       case ICMD_DADD:
+                       case ICMD_DSUB:
+                       case ICMD_DMUL:
+                       case ICMD_DDIV:
+                       case ICMD_DREM:
                        case ICMD_DNEG:
+                               dv->type = TYPE_DBL;
+                               break;
 
+                       case ICMD_INLINE_START:
+                       case ICMD_INLINE_END:
+                               break;
 
-                               /*XXX What shall we do with the following ?*/
+                               /* XXX What shall we do with the following ?*/
                        case ICMD_AASTORECONST:
                                TYPECHECK_COUNT(stat_ins_unchecked);
                                break;
@@ -2348,13 +2269,10 @@ return_tail:
                        default:
                                LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
                                TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
-#endif
                }
 
-               /* the output of this instruction becomes the current stack */
-               state->curstack = dst;
-
                /* reach exception handlers for this instruction */
+
                if (maythrow) {
                        TYPECHECK_COUNT(stat_ins_maythrow);
                        TYPECHECK_MARK(state->stat_maythrow);
@@ -2363,39 +2281,42 @@ return_tail:
                        while (state->handlers[i]) {
                                TYPECHECK_COUNT(stat_handlers_reached);
                                if (state->handlers[i]->catchtype.any)
-                                       state->excstack.typeinfo.typeclass = state->handlers[i]->catchtype;
+                                       VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
                                else
-                                       state->excstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
+                                       VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
                                if (!typestate_reach(state,
                                                state->handlers[i]->handler,
-                                               &(state->excstack),state->localset))
+                                               &(state->exinvars), jd->var, 1))
                                        return false;
                                i++;
                        }
                }
 
-               LOG("next instruction");
+               LOG("\t\tnext instruction");
                state->iptr++;
        } /* while instructions */
 
        LOG("instructions done");
        LOGSTR("RESULT=> ");
-       DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
+       DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
+                               state->bptr->outdepth));
+       DOLOG(typevector_print(stdout, jd->var, state->numlocals));
        LOGNL; LOGFLUSH;
 
        /* propagate stack and variables to the following block */
        if (!superblockend) {
                LOG("reaching following block");
-               tbptr = state->bptr + 1;
+               tbptr = state->bptr->next;
                while (tbptr->flags == BBDELETED) {
-                       tbptr++;
+                       tbptr = tbptr->next;
 #ifdef TYPECHECK_DEBUG
                        /* this must be checked in parse.c */
-                       if ((tbptr->debug_nr) >= state->m->basicblockcount)
+                       if ((tbptr->nr) >= state->basicblockcount)
                                TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
 #endif
                }
-               if (!typestate_reach(state,tbptr,dst,state->localset))
+               if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
+                                       state->bptr->outdepth))
                        return false;
        }
 
@@ -2403,12 +2324,13 @@ return_tail:
         * have been saved if an <init> call inside the block has
         * modified the instack types. (see INVOKESPECIAL) */
 
-       if (state->savedstack)
-               typestate_restore_instack(state);
+       if (state->savedinvars)
+               typestate_restore_invars(state);
 
        return true;
 }
 
+
 /* verify_init_locals **********************************************************
  
    Initialize the local variables in the verifier state.
@@ -2426,17 +2348,13 @@ static bool
 verify_init_locals(verifier_state *state)
 {
        int i;
-       typedescriptor *td;
-       typevector *lset;
-
-    /* initialize the variable types of the first block */
-    /* to the types of the arguments */
+       int index;
+       varinfo *locals;
+       varinfo *v;
+       jitdata *jd = state->jd;
+       int skip = 0;
 
-       lset = MGET_TYPEVECTOR(state->localbuf,0,state->numlocals);
-       lset->k = 0;
-       lset->alt = NULL;
-       td = lset->td;
-       i = state->validlocals;
+       locals = state->basicblocks[0].inlocals;
 
        /* allocate parameter descriptors if necessary */
        
@@ -2444,45 +2362,49 @@ verify_init_locals(verifier_state *state)
                if (!descriptor_params_from_paramtypes(state->m->parseddesc,state->m->flags))
                        return false;
 
+       /* pre-initialize variables as TYPE_VOID */
+       
+       i = state->numlocals;
+       v = locals;
+       while (i--) {
+               v->type = TYPE_VOID;
+               v++;
+       }
+
     /* if this is an instance method initialize the "this" ref type */
        
     if (!(state->m->flags & ACC_STATIC)) {
-               if (!i)
-                       TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
-        td->type = TYPE_ADDRESS;
-        if (state->initmethod)
-            TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
-        else
-            typeinfo_init_classinfo(&(td->info), state->m->class);
-        td++;
-               i--;
+               index = jd->local_map[5*0 + TYPE_ADR];
+               if (index != UNUSED) {
+                       if (state->validlocals < 1)
+                               TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
+                       v = locals + index;
+                       v->type = TYPE_ADR;
+                       if (state->initmethod)
+                               TYPEINFO_INIT_NEWOBJECT(v->typeinfo, NULL);
+                       else
+                               typeinfo_init_classinfo(&(v->typeinfo), state->m->class);
+               }
+
+               skip = 1;
     }
 
     LOG("'this' argument set.\n");
 
     /* the rest of the arguments and the return type */
        
-    i = typedescriptors_init_from_methoddesc(td, state->m->parseddesc,
-                                                                                         i,
-                                                                                         true, /* two word types use two slots */
-                                                                                         (td - lset->td), /* skip 'this' pointer */
-                                                                                         &state->returntype);
-       if (i == -1)
+    if (!typeinfo_init_varinfos_from_methoddesc(locals, state->m->parseddesc,
+                                                                                         state->validlocals,
+                                                                                         skip, /* skip 'this' pointer */
+                                                                                         jd->local_map,
+                                                                                         &state->returntype))
                return false;
-       td += i;
-
-       /* variables not used for arguments are initialized to TYPE_VOID */
-       
-       i = state->numlocals - (td - lset->td);
-       while (i--) {
-               td->type = TYPE_VOID;
-               td++;
-       }
 
     LOG("Arguments set.\n");
        return true;
 }
 
+
 /* typecheck_init_flags ********************************************************
  
    Initialize the basic block flags for the following CFG traversal.
@@ -2500,16 +2422,13 @@ typecheck_init_flags(verifier_state *state)
 
     /* set all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
        
-    i = state->m->basicblockcount;
-    block = state->m->basicblocks;
-
-    while (--i >= 0) {
+    i = state->basicblockcount;
+    for (block = state->basicblocks; block; block = block->next) {
                
 #ifdef TYPECHECK_DEBUG
                /* check for invalid flags */
         if (block->flags != BBFINISHED && block->flags != BBDELETED && block->flags != BBUNDEF)
         {
-            /*show_icmd_method(state->cd->method,state->cd,state->rd);*/
             LOGSTR1("block flags: %d\n",block->flags); LOGFLUSH;
                        TYPECHECK_ASSERT(false);
         }
@@ -2518,15 +2437,15 @@ typecheck_init_flags(verifier_state *state)
         if (block->flags >= BBFINISHED) {
             block->flags = BBTYPECHECK_UNDEF;
         }
-        block++;
     }
 
     /* the first block is always reached */
        
-    if (state->m->basicblockcount && state->m->basicblocks[0].flags == BBTYPECHECK_UNDEF)
-        state->m->basicblocks[0].flags = BBTYPECHECK_REACHED;
+    if (state->basicblockcount && state->basicblocks[0].flags == BBTYPECHECK_UNDEF)
+        state->basicblocks[0].flags = BBTYPECHECK_REACHED;
 }
 
+
 /* typecheck_reset_flags *******************************************************
  
    Reset the flags of basic blocks we have not reached.
@@ -2539,34 +2458,35 @@ typecheck_init_flags(verifier_state *state)
 static void
 typecheck_reset_flags(verifier_state *state)
 {
-       s4 i;
+       basicblock *block;
 
        /* check for invalid flags at exit */
        
 #ifdef TYPECHECK_DEBUG
-       for (i=0; i<state->m->basicblockcount; ++i) {
-               if (state->m->basicblocks[i].flags != BBDELETED
-                       && state->m->basicblocks[i].flags != BBUNDEF
-                       && state->m->basicblocks[i].flags != BBFINISHED
-                       && state->m->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
+       for (block = state->basicblocks; block; block = block->next) {
+               if (block->flags != BBDELETED
+                       && block->flags != BBUNDEF
+                       && block->flags != BBFINISHED
+                       && block->flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
                                                                                                         * some exception handlers,
                                                                                                         * that's ok. */
                {
                        LOG2("block L%03d has invalid flags after typecheck: %d",
-                                state->m->basicblocks[i].debug_nr,state->m->basicblocks[i].flags);
+                                block->nr,block->flags);
                        TYPECHECK_ASSERT(false);
                }
        }
 #endif
        
-       /* Reset blocks we never reached */
+       /* Delete blocks we never reached */
        
-       for (i=0; i<state->m->basicblockcount; ++i) {
-               if (state->m->basicblocks[i].flags == BBTYPECHECK_UNDEF)
-                       state->m->basicblocks[i].flags = BBFINISHED;
+       for (block = state->basicblocks; block; block = block->next) {
+               if (block->flags == BBTYPECHECK_UNDEF)
+                       block->flags = BBDELETED;
        }
 }
-               
+
+
 /****************************************************************************/
 /* typecheck()                                                              */
 /* This is the main function of the bytecode verifier. It is called         */
@@ -2578,20 +2498,21 @@ typecheck_reset_flags(verifier_state *state)
 /*    rdata............registerdata for the method                          */
 /*                                                                          */
 /* RETURN VALUE:                                                            */
-/*     m................successful verification                             */
-/*     NULL.............an exception has been thrown                        */
+/*     true.............successful verification                             */
+/*     false............an exception has been thrown                        */
 /*                                                                          */
-/* XXX TODO:                                                                */
-/*     Bytecode verification has not been tested with inlining and          */
-/*     probably does not work correctly with inlining.                      */
 /****************************************************************************/
 
 #define MAXPARAMS 255
 
-methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
+bool typecheck(jitdata *jd)
 {
-       verifier_state state;             /* current state of the verifier */
-    int i;                                        /* temporary counter */
+       methodinfo     *meth;
+       codegendata    *cd;
+       varinfo        *savedlocals;
+       verifier_state  state;             /* current state of the verifier */
+       s4              i;
+       s4              t;
 
        /* collect statistics */
 
@@ -2604,28 +2525,28 @@ methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
        state.stat_maythrow = false;
 #endif
 
+       /* get required compiler data */
+
+       meth = jd->m;
+       cd   = jd->cd;
+
        /* some logging on entry */
 
+
     LOGSTR("\n==============================================================================\n");
-    /*DOLOG( show_icmd_method(cdata->method,cdata,rdata));*/
+    DOLOG( show_method(jd, SHOW_STACK) );
     LOGSTR("\n==============================================================================\n");
-    LOGimpSTR("Entering typecheck: ");
-    LOGimpSTRu(cdata->method->name);
-    LOGimpSTR("    ");
-    LOGimpSTRu(cdata->method->descriptor);
-    LOGimpSTR("    (class ");
-    LOGimpSTRu(cdata->method->class->name);
-    LOGimpSTR(")\n");
-       LOGFLUSH;
+    LOGMETHOD("Entering typecheck: ",cd->method);
 
        /* initialize the verifier state */
 
-       state.savedstackbuf = NULL;
-       state.savedstack = NULL;
-       state.jsrencountered = false;
        state.m = meth;
-       state.cd = cdata;
-       state.rd = rdata;
+       state.jd = jd;
+       state.cd = cd;
+       state.basicblockcount = jd->basicblockcount;
+       state.basicblocks = jd->basicblocks;
+       state.savedindices = NULL;
+       state.savedinvars = NULL;
 
        /* check if this method is an instance initializer method */
 
@@ -2641,31 +2562,45 @@ methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
     /* the 'this' reference has been initialized.                           */
        /*         TYPE_VOID...means 'this' has not been initialized,           */
        /*         TYPE_INT....means 'this' has been initialized.               */
-    state.numlocals = state.cd->maxlocals;
-       state.validlocals = state.numlocals;
-    if (state.initmethod) state.numlocals++;
 
-    /* allocate the buffers for local variables */
-       
-       state.localbuf = DMNEW_TYPEVECTOR(state.m->basicblockcount+1, state.numlocals);
-       state.localset = MGET_TYPEVECTOR(state.localbuf,state.m->basicblockcount,state.numlocals);
+    state.numlocals = state.jd->localcount;
+       state.validlocals = state.numlocals;
+    if (state.initmethod) 
+               state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
+
+       state.reverselocalmap = DMNEW(s4, state.validlocals);
+       for (i=0; i<jd->m->maxlocals; ++i)
+               for (t=0; t<5; ++t) {
+                       s4 mapped = jd->local_map[5*i + t];
+                       if (mapped >= 0)
+                               state.reverselocalmap[mapped] = i;
+               }
 
-    LOG("Variable buffer allocated.\n");
+       DOLOG(
+               LOG("reverselocalmap:");
+               for (i=0; i<state.validlocals; ++i) {
+                       LOG2("    %i => javaindex %i", i, state.reverselocalmap[i]);
+               });
 
     /* allocate the buffer of active exception handlers */
        
     state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
 
+       /* save local variables */
+
+       savedlocals = DMNEW(varinfo, state.numlocals);
+       MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
+
        /* initialized local variables of first block */
 
        if (!verify_init_locals(&state))
-               return NULL;
+               return false;
 
-    /* initialize the input stack of exception handlers */
+    /* initialize invars of exception handlers */
        
-       state.excstack.prev = NULL;
-       state.excstack.type = TYPE_ADR;
-       typeinfo_init_classinfo(&(state.excstack.typeinfo),
+       state.exinvars = state.numlocals;
+       VAR(state.exinvars)->type = TYPE_ADR;
+       typeinfo_init_classinfo(&(VAR(state.exinvars)->typeinfo),
                                                        class_java_lang_Throwable); /* changed later */
 
     LOG("Exception handler stacks set.\n");
@@ -2676,21 +2611,19 @@ methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
 
         state.repeat = false;
         
-        i = state.m->basicblockcount;
-        state.bptr = state.m->basicblocks;
+        state.bptr = state.basicblocks;
 
-        while (--i >= 0) {
-            LOGSTR1("---- BLOCK %04d, ",state.bptr->debug_nr);
+        for (; state.bptr; state.bptr = state.bptr->next) {
+            LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
             LOGSTR1("blockflags: %d\n",state.bptr->flags);
             LOGFLUSH;
             
                    /* verify reached block */  
             if (state.bptr->flags == BBTYPECHECK_REACHED) {
                 if (!verify_basic_block(&state))
-                                       return NULL;
+                                       return false;
             }
-            state.bptr++;
-        } /* while blocks */
+        } /* for blocks */
 
         LOGIF(state.repeat,"state.repeat == true");
     } while (state.repeat);
@@ -2708,12 +2641,16 @@ methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
 
        typecheck_reset_flags(&state);
 
-       /* just return methodinfo* to indicate everything was ok */
+       /* restore locals */
+
+       MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
+
+       /* everything's ok */
+
     LOGimp("exiting typecheck");
-       return state.m;
+       return true;
 }
-
-#endif /* CACAO_TYPECHECK */
+#endif /* ENABLE_VERIFIER */
 
 /*
  * These are local overrides for various environment variables in Emacs.