* Removed all Id tags.
[cacao.git] / src / vm / resolve.c
index 7cec6e9fc52248e6606c618423aa49fdeda6c5f7..a1235b901100bde201f9ae49dd6e557447405ff8 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/resolve.c - resolving classes/interfaces/fields/methods
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Edwin Steiner
-
-   Changes: Christan Thalinger
-
-   $Id: resolve.c 4357 2006-01-22 23:33:38Z twisti $
-
 */
 
 
+#include "config.h"
+
 #include <assert.h>
 
+#include "vm/types.h"
+
 #include "mm/memory.h"
-#include "vm/resolve.h"
+
 #include "vm/access.h"
-#include "vm/classcache.h"
-#include "vm/descriptor.h"
 #include "vm/exceptions.h"
-#include "vm/linker.h"
-#include "vm/loader.h"
-#include "vm/stringlocal.h"
+#include "vm/global.h"
+#include "vm/primitive.h"
+#include "vm/resolve.h"
+
 #include "vm/jit/jit.h"
 #include "vm/jit/verify/typeinfo.h"
 
+#include "vmcore/classcache.h"
+#include "vmcore/descriptor.h"
+#include "vmcore/linker.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+
 
 /******************************************************************************/
 /* DEBUG HELPERS                                                              */
@@ -100,10 +101,13 @@ bool resolve_class_from_name(classinfo *referer,
                                                         bool link,
                                                         classinfo **result)
 {
-       classinfo *cls = NULL;
-       char *utf_ptr;
-       int len;
-       
+       classinfo *cls;
+       char      *utf_ptr;
+       int        len;
+       char      *msg;
+       s4         msglen;
+       utf       *u;
+
        assert(result);
        assert(referer);
        assert(classname);
@@ -112,11 +116,11 @@ bool resolve_class_from_name(classinfo *referer,
        *result = NULL;
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"resolve_class_from_name(");
-       utf_fprint(stderr,referer->name);
-       fprintf(stderr,",%p,",referer->classloader);
-       utf_fprint(stderr,classname);
-       fprintf(stderr,",%d,%d)\n",(int)checkaccess,(int)link);
+       printf("resolve_class_from_name(");
+       utf_fprint_printable_ascii(stdout,referer->name);
+       printf(",%p,",(void*)referer->classloader);
+       utf_fprint_printable_ascii(stdout,classname);
+       printf(",%d,%d)\n",(int)checkaccess,(int)link);
 #endif
 
        /* lookup if this class has already been loaded */
@@ -124,7 +128,7 @@ bool resolve_class_from_name(classinfo *referer,
        cls = classcache_lookup(referer->classloader, classname);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    lookup result: %p\n",(void*)cls);
+       printf("    lookup result: %p\n",(void*)cls);
 #endif
 
        if (!cls) {
@@ -165,14 +169,22 @@ bool resolve_class_from_name(classinfo *referer,
                }
 
 #ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"    loading...\n");
+               printf("    loading...\n");
 #endif
 
                /* load the class */
-               if (!cls) {
-                       if (!(cls = load_class_from_classloader(classname,
-                                                                                                       referer->classloader)))
-                               return false; /* exception */
+
+               if (cls == NULL) {
+                       cls = load_class_from_classloader(classname, referer->classloader);
+
+                       if (cls == NULL) {
+                               /* If the exception is a ClassNotFoundException,
+                                  convert it to a NoClassDefFoundError. */
+
+                               exceptions_classnotfoundexception_to_noclassdeffounderror();
+
+                               return false;
+                       }
                }
        }
 
@@ -181,23 +193,31 @@ bool resolve_class_from_name(classinfo *referer,
        assert(cls->state & CLASS_LOADED);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    checking access rights...\n");
+       printf("    checking access rights...\n");
 #endif
        
        /* check access rights of referer to refered class */
+
        if (checkaccess && !access_is_accessible_class(referer,cls)) {
-               int msglen;
-               char *message;
-
-               msglen = utf_strlen(cls->name) + utf_strlen(referer->name) + 100;
-               message = MNEW(char,msglen);
-               strcpy(message,"class is not accessible (");
-               utf_sprint_classname(message+strlen(message),cls->name);
-               strcat(message," from ");
-               utf_sprint_classname(message+strlen(message),referer->name);
-               strcat(message,")");
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
-               MFREE(message,char,msglen);
+               msglen =
+                       utf_bytes(cls->name) +
+                       utf_bytes(referer->name) +
+                       100;
+
+               msg = MNEW(char, msglen);
+
+               strcpy(msg, "class is not accessible (");
+               utf_cat_classname(msg, cls->name);
+               strcat(msg, " from ");
+               utf_cat_classname(msg, referer->name);
+               strcat(msg, ")");
+
+               u = utf_new_char(msg);
+
+               MFREE(msg, char, msglen);
+
+               exceptions_throw_illegalaccessexception(u);
+
                return false; /* exception */
        }
 
@@ -212,7 +232,7 @@ bool resolve_class_from_name(classinfo *referer,
 
        /* resolution succeeds */
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    success.\n");
+       printf("    success.\n");
 #endif
        *result = cls;
        return true;
@@ -260,7 +280,10 @@ bool resolve_classref(methodinfo *refmethod,
 /* resolve_classref_or_classinfo ***********************************************
  
    Resolve a symbolic class reference if necessary
-  
+
+   NOTE: If given, refmethod->class is used as the referring class.
+         Otherwise, cls.ref->referer is used.
+
    IN:
        refmethod........the method from which resolution was triggered
                         (may be NULL if not applicable)
@@ -294,15 +317,16 @@ bool resolve_classref_or_classinfo(methodinfo *refmethod,
                                                                   classinfo **result)
 {
        classinfo         *c;
+       classinfo         *referer;
        
        assert(cls.any);
        assert(mode == resolveEager || mode == resolveLazy);
        assert(result);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"resolve_classref_or_classinfo(");
-       utf_fprint(stderr,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
-       fprintf(stderr,",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
+       printf("resolve_classref_or_classinfo(");
+       utf_fprint_printable_ascii(stdout,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
+       printf(",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
 #endif
 
        *result = NULL;
@@ -310,7 +334,18 @@ bool resolve_classref_or_classinfo(methodinfo *refmethod,
        if (IS_CLASSREF(cls)) {
                /* we must resolve this reference */
 
-               if (!resolve_class_from_name(cls.ref->referer, refmethod, cls.ref->name,
+               /* determine which class to use as the referer */
+
+               /* Common cases are refmethod == NULL or both referring classes */
+               /* being the same, so the referer usually is cls.ref->referer.    */
+               /* There is one important case where it is not: When we do a      */
+               /* deferred assignability check to a formal argument of a method, */
+               /* we must use refmethod->class (the caller's class) to resolve   */
+               /* the type of the formal argument.                               */
+
+               referer = (refmethod) ? refmethod->class : cls.ref->referer;
+
+               if (!resolve_class_from_name(referer, refmethod, cls.ref->name,
                                                                         mode, checkaccess, link, &c))
                        goto return_exception;
 
@@ -345,6 +380,33 @@ bool resolve_classref_or_classinfo(methodinfo *refmethod,
 }
 
 
+/* resolve_classref_or_classinfo_eager *****************************************
+   Resolve a symbolic class reference eagerly if necessary.
+   No attempt is made to link the class.
+
+   IN:
+       cls..............class reference or classinfo
+       checkaccess......if true, access rights to the class are checked
+  
+   RETURN VALUE:
+       classinfo *......the resolved class
+       NULL.............an exception has been thrown
+   
+*******************************************************************************/
+
+classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls,
+                                                                                          bool checkaccess)
+{
+       classinfo *c;
+
+       if (!resolve_classref_or_classinfo(NULL, cls, resolveEager, checkaccess, false, &c))
+               return NULL;
+
+       return c;
+}
+
+
 /* resolve_class_from_typedesc *************************************************
  
    Return a classinfo * for the given type descriptor
@@ -365,7 +427,7 @@ bool resolve_classref_or_classinfo(methodinfo *refmethod,
        false............an exception has been thrown
 
    NOTE:
-       This function always resolved eagerly.
+       This function always resolves eagerly.
    
 *******************************************************************************/
 
@@ -379,31 +441,36 @@ bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, class
        *result = NULL;
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"resolve_class_from_typedesc(");
-       descriptor_debug_print_typedesc(stderr,d);
-       fprintf(stderr,",%i,%i)\n",(int)checkaccess,(int)link);
+       printf("resolve_class_from_typedesc(");
+       descriptor_debug_print_typedesc(stdout,d);
+       printf(",%i,%i)\n",(int)checkaccess,(int)link);
 #endif
 
-       if (d->classref) {
+       if (d->type == TYPE_ADR) {
                /* a reference type */
+               assert(d->classref);
                if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
                                                                                   resolveEager,checkaccess,link,&cls))
                        return false; /* exception */
        }
        else {
                /* a primitive type */
-               cls = primitivetype_table[d->decltype].class_primitive;
+
+               cls = primitive_class_get_by_type(d->decltype);
+
                assert(cls->state & CLASS_LOADED);
+
                if (!(cls->state & CLASS_LINKED))
                        if (!link_class(cls))
                                return false; /* exception */
        }
+
        assert(cls);
        assert(cls->state & CLASS_LOADED);
        assert(!link || (cls->state & CLASS_LINKED));
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
+       printf("    result = ");utf_fprint_printable_ascii(stdout,cls->name);printf("\n");
 #endif
 
        *result = cls;
@@ -414,21 +481,286 @@ bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, class
 /* SUBTYPE SET CHECKS                                                         */
 /******************************************************************************/
 
-#ifdef ENABLE_VERIFIER
+/* resolve_subtype_check *******************************************************
+   Resolve the given types lazily and perform a subtype check
+  
+   IN:
+       refmethod........the method triggering the resolution
+       subtype..........checked to be a subtype of supertype
+          supertype........the super type to check agaings
+          mode.............mode of resolution:
+                            resolveLazy...only resolve if it does not
+                                          require loading classes
+                            resolveEager..load classes if necessary
+       error............which type of exception to throw if
+                        the test fails. May be:
+                            resolveLinkageError, or
+                            resolveIllegalAccessError
+                                               IMPORTANT: If error==resolveIllegalAccessError,
+                                               then array types are not checked.
+
+   RETURN VALUE:
+       resolveSucceeded.....the check succeeded
+       resolveDeferred......the check could not be performed due to
+                               unresolved types. (This can only happen for
+                                                       mode == resolveLazy.)
+          resolveFailed........the check failed, an exception has been thrown.
+   
+   NOTE:
+          The types are resolved first, so any
+          exception which may occurr during resolution may
+          be thrown by this function.
+   
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+static resolve_result_t resolve_subtype_check(methodinfo *refmethod,
+                                                                                     classref_or_classinfo subtype,
+                                                                                         classref_or_classinfo supertype,
+                                                                                         resolve_mode_t mode,
+                                                                                         resolve_err_t error)
+{
+       classinfo        *subclass;
+       typeinfo          subti;
+       typecheck_result  r;
+       char             *msg;
+       s4                msglen;
+       utf              *u;
+
+       assert(refmethod);
+       assert(subtype.any);
+       assert(supertype.any);
+       assert(mode == resolveLazy || mode == resolveEager);
+       assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+
+       /* resolve the subtype */
+
+       if (!resolve_classref_or_classinfo(refmethod,subtype,mode,false,true,&subclass)) {
+               /* the subclass could not be resolved. therefore we are sure that  */
+               /* no instances of this subclass will ever exist -> skip this test */
+               /* XXX this assumes that class loading has invariant results (as in JVM spec) */
+               exceptions_clear_exception();
+               return resolveSucceeded;
+       }
+       if (!subclass)
+               return resolveDeferred; /* be lazy */
+
+       assert(subclass->state & CLASS_LINKED);
+
+       /* do not check access to protected members of arrays */
+
+       if (error == resolveIllegalAccessError && subclass->name->text[0] == '[') {
+               return resolveSucceeded;
+       }
+
+       /* perform the subtype check */
+
+       typeinfo_init_classinfo(&subti,subclass);
+check_again:
+       r = typeinfo_is_assignable_to_class(&subti,supertype);
+       if (r == typecheck_FAIL)
+               return resolveFailed; /* failed, exception is already set */
+
+       if (r == typecheck_MAYBE) {
+               assert(IS_CLASSREF(supertype));
+               if (mode == resolveEager) {
+                       if (!resolve_classref_or_classinfo(refmethod,supertype,
+                                                                                          resolveEager,false,true,
+                                                                                          &supertype.cls))
+                       {
+                               return resolveFailed;
+                       }
+                       assert(supertype.cls);
+                       goto check_again;
+               }
+
+               return resolveDeferred; /* be lazy */
+       }
+
+       if (!r) {
+               /* sub class relationship is false */
+
+#if defined(RESOLVE_VERBOSE)
+               printf("SUBTYPE CHECK FAILED!\n");
+#endif
+
+               msglen =
+                       utf_bytes(subclass->name) +
+                       utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype))
+                       + 200;
+
+               msg = MNEW(char, msglen);
+
+               strcpy(msg, (error == resolveIllegalAccessError) ?
+                          "illegal access to protected member (" :
+                          "subtype constraint violated (");
+
+               utf_cat_classname(msg, subclass->name);
+               strcat(msg, " is not a subclass of ");
+               utf_cat_classname(msg, CLASSREF_OR_CLASSINFO_NAME(supertype));
+               strcat(msg, ")");
+
+               u = utf_new_char(msg);
+
+               if (error == resolveIllegalAccessError)
+                       exceptions_throw_illegalaccessexception(u);
+               else
+                       exceptions_throw_linkageerror(msg, NULL);
+
+               /* ATTENTION: We probably need msg for
+                  exceptions_throw_linkageerror. */
+
+               MFREE(msg, char, msglen);
+
+               return resolveFailed; /* exception */
+       }
+
+       /* everything ok */
+
+       return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/* resolve_lazy_subtype_checks *************************************************
+   Resolve the types to check lazily and perform subtype checks
+  
+   IN:
+       refmethod........the method triggering the resolution
+       subtinfo.........the typeinfo containing the subtypes
+       supertype........the supertype to test againgst
+          mode.............mode of resolution:
+                            resolveLazy...only resolve if it does not
+                                          require loading classes
+                            resolveEager..load classes if necessary
+       error............which type of exception to throw if
+                        the test fails. May be:
+                            resolveLinkageError, or
+                            resolveIllegalAccessError
+                                               IMPORTANT: If error==resolveIllegalAccessError,
+                                               then array types in the set are skipped.
+
+   RETURN VALUE:
+       resolveSucceeded.....the check succeeded
+       resolveDeferred......the check could not be performed due to
+                               unresolved types
+          resolveFailed........the check failed, an exception has been thrown.
+   
+   NOTE:
+       The references in the set are resolved first, so any
+       exception which may occurr during resolution may
+       be thrown by this function.
+   
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
+                                                                                                       typeinfo *subtinfo,
+                                                                                                       classref_or_classinfo supertype,
+                                                                                                       resolve_err_t error)
+{
+       int count;
+       int i;
+       resolve_result_t result;
+
+       assert(refmethod);
+       assert(subtinfo);
+       assert(supertype.any);
+       assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+
+       /* returnAddresses are illegal here */
+
+       if (TYPEINFO_IS_PRIMITIVE(*subtinfo)) {
+               exceptions_throw_verifyerror(refmethod,
+                               "Invalid use of returnAddress");
+               return resolveFailed;
+       }
+
+       /* uninitialized objects are illegal here */
+
+       if (TYPEINFO_IS_NEWOBJECT(*subtinfo)) {
+               exceptions_throw_verifyerror(refmethod,
+                               "Invalid use of uninitialized object");
+               return resolveFailed;
+       }
+
+       /* the nulltype is always assignable */
+
+       if (TYPEINFO_IS_NULLTYPE(*subtinfo))
+               return resolveSucceeded;
+
+       /* every type is assignable to (BOOTSTRAP)java.lang.Object */
+
+       if (supertype.cls == class_java_lang_Object
+               || (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
+                       && refmethod->class->classloader == NULL))
+       {
+               return resolveSucceeded;
+       }
+
+       if (subtinfo->merged) {
+
+               /* for a merged type we have to do a series of checks */
+
+               count = subtinfo->merged->count;
+               for (i=0; i<count; ++i) {
+                       classref_or_classinfo c = subtinfo->merged->list[i];
+                       if (subtinfo->dimension > 0) {
+                               /* a merge of array types */
+                               /* the merged list contains the possible _element_ types, */
+                               /* so we have to create array types with these elements.  */
+                               if (IS_CLASSREF(c)) {
+                                       c.ref = class_get_classref_multiarray_of(subtinfo->dimension,c.ref);
+                               }
+                               else {
+                                       c.cls = class_multiarray_of(subtinfo->dimension,c.cls,false);
+                               }
+                       }
+
+                       /* do the subtype check against the type c */
+
+                       result = resolve_subtype_check(refmethod,c,supertype,resolveLazy,error);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+       }
+       else {
+
+               /* a single type, this is the common case, hopefully */
+
+               if (CLASSREF_OR_CLASSINFO_NAME(subtinfo->typeclass)
+                       == CLASSREF_OR_CLASSINFO_NAME(supertype))
+               {
+                       /* the class names are the same */
+                   /* equality is guaranteed by the loading constraints */
+                       return resolveSucceeded;
+               }
+               else {
+
+                       /* some other type name, try to perform the check lazily */
+
+                       return resolve_subtype_check(refmethod,
+                                                                                subtinfo->typeclass,supertype,
+                                                                                resolveLazy,
+                                                                                error);
+               }
+       }
+
+       /* everything ok */
+       return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
 
 /* resolve_and_check_subtype_set ***********************************************
  
    Resolve the references in the given set and test subtype relationships
   
    IN:
-       referer..........the class containing the references
        refmethod........the method triggering the resolution
        ref..............a set of class/interface references
                         (may be empty)
-       type.............the type to test against the set
-       reversed.........if true, test if type is a subtype of
-                        the set members, instead of the other
-                        way round
+       typeref..........the type to test against the set
        mode.............mode of resolution:
                             resolveLazy...only resolve if it does not
                                           require loading classes
@@ -440,17 +772,12 @@ bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, class
                                                IMPORTANT: If error==resolveIllegalAccessError,
                                                then array types in the set are skipped.
 
-   OUT:
-       *checked.........set to true if all checks were performed,
-                           otherwise set to false
-                           (This is guaranteed to be true if mode was
-                                               resolveEager and no exception occured.)
-                                               If checked == NULL, this parameter is not used.
-  
    RETURN VALUE:
-       true.............the check succeeded
-       false............the check failed. An exception has been
-                        thrown.
+       resolveSucceeded.....the check succeeded
+       resolveDeferred......the check could not be performed due to
+                               unresolved types. (This can only happen if
+                                                       mode == resolveLazy.)
+          resolveFailed........the check failed, an exception has been thrown.
    
    NOTE:
        The references in the set are resolved first, so any
@@ -459,145 +786,62 @@ bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, class
    
 *******************************************************************************/
 
-bool resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
-                                                                  unresolved_subtype_set *ref,
-                                                                  classref_or_classinfo typeref,
-                                                                  bool reversed,
-                                                                  resolve_mode_t mode,
-                                                                  resolve_err_t error,
-                                                                  bool *checked)
+#if defined(ENABLE_VERIFIER)
+static resolve_result_t resolve_and_check_subtype_set(methodinfo *refmethod,
+                                                                         unresolved_subtype_set *ref,
+                                                                         classref_or_classinfo typeref,
+                                                                         resolve_mode_t mode,
+                                                                         resolve_err_t error)
 {
        classref_or_classinfo *setp;
-       classinfo *result;
-       classinfo *type;
-       typeinfo resultti;
-       typeinfo typeti;
-       char *message;
-       int msglen;
-       typecheck_result r;
+       typecheck_result checkresult;
 
-       assert(referer);
+       assert(refmethod);
        assert(ref);
        assert(typeref.any);
        assert(mode == resolveLazy || mode == resolveEager);
        assert(error == resolveLinkageError || error == resolveIllegalAccessError);
 
-#ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"resolve_and_check_subtype_set\n");
-       unresolved_subtype_set_debug_dump(ref,stderr);
-       if (IS_CLASSREF(typeref)) {
-               fprintf(stderr,"    ref: ");utf_fprint(stderr,typeref.ref->name);
-       }
-       else {
-               fprintf(stderr,"    cls: ");utf_fprint(stderr,typeref.cls->name);
-       }
-       fprintf(stderr,"\n");
+#if defined(RESOLVE_VERBOSE)
+       printf("resolve_and_check_subtype_set:\n");
+       unresolved_subtype_set_debug_dump(ref, stdout);
+       if (IS_CLASSREF(typeref))
+               class_classref_println(typeref.ref);
+       else
+               class_println(typeref.cls);
 #endif
 
        setp = ref->subtyperefs;
 
        /* an empty set of tests always succeeds */
        if (!setp || !setp->any) {
-               if (checked)
-                       *checked = true;
-               return true;
+               return resolveSucceeded;
        }
 
-       if (checked)
-               *checked = false;
-
        /* first resolve the type if necessary */
-       if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&type))
-               return false; /* exception */
-       if (!type)
-               return true; /* be lazy */
-
-       assert(type);
-       assert(type->state & CLASS_LOADED);
-       assert(type->state & CLASS_LINKED);
-       typeinfo_init_classinfo(&typeti,type);
-
-       for (; setp->any; ++setp) {
-               /* first resolve the set member if necessary */
-               if (!resolve_classref_or_classinfo(refmethod,*setp,mode,false,true,&result)) {
-                       /* the type could not be resolved. therefore we are sure that  */
-                       /* no instances of this type will ever exist -> skip this test */
-                       /* XXX this assumes that class loading has invariant results (as in JVM spec) */
-                       *exceptionptr = NULL;
-                       continue;
-               }
-               if (!result)
-                       return true; /* be lazy */
-
-               assert(result);
-               assert(result->state & CLASS_LOADED);
-               assert(result->state & CLASS_LINKED);
+       if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&(typeref.cls)))
+               return resolveFailed; /* exception */
+       if (!typeref.cls)
+               return resolveDeferred; /* be lazy */
 
+       assert(typeref.cls->state & CLASS_LINKED);
 
-               /* do not check access to protected members of arrays */
-               if (error == resolveIllegalAccessError && result->name->text[0] == '[') {
-                       continue;
-               }
-
-#ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"performing subclass test:\n");
-               fprintf(stderr,"    ");utf_fprint(stderr,result->name);fputc('\n',stderr);
-               fprintf(stderr,"  must be a %s of\n",(reversed) ? "superclass" : "subclass");
-               fprintf(stderr,"    ");utf_fprint(stderr,type->name);fputc('\n',stderr);
-#endif
+       /* iterate over the set members */
 
-               /* now check the subtype relationship */
-               typeinfo_init_classinfo(&resultti,result);
-               if (reversed) {
-                       /* we must test against `true` because `MAYBE` is also != 0 */
-                       r = typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result));
-                       if (r == typecheck_FAIL)
-                               return false;
-                       if (r != typecheck_TRUE) {
-#ifdef RESOLVE_VERBOSE
-                               fprintf(stderr,"reversed subclass test failed\n");
-#endif
-                               goto throw_error;
-                       }
-               }
-               else {
-                       /* we must test against `true` because `MAYBE` is also != 0 */
-                       r = typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type));
-                       if (r == typecheck_FAIL)
-                               return false;
-                       if (r != typecheck_TRUE) {
-#ifdef RESOLVE_VERBOSE
-                               fprintf(stderr,"subclass test failed\n");
+       for (; setp->any; ++setp) {
+               checkresult = resolve_subtype_check(refmethod,*setp,typeref,mode,error);
+#if defined(RESOLVE_VERBOSE)
+               if (checkresult != resolveSucceeded)
+                       printf("SUBTYPE CHECK FAILED!\n");
 #endif
-                               goto throw_error;
-                       }
-               }
+               if (checkresult != resolveSucceeded)
+                       return checkresult;
        }
-       
-       /* check succeeds */
-       if (checked)
-               *checked = true;
-       return true;
 
-throw_error:
-       msglen = utf_strlen(result->name) + utf_strlen(type->name) + 200;
-       message = MNEW(char,msglen);
-       strcpy(message,(error == resolveIllegalAccessError) ?
-                       "illegal access to protected member ("
-                       : "subtype constraint violated (");
-       utf_sprint_classname(message+strlen(message),result->name);
-       strcat(message," is not a subclass of ");
-       utf_sprint_classname(message+strlen(message),type->name);
-       strcat(message,")");
-       if (error == resolveIllegalAccessError)
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
-       else
-               *exceptionptr = exceptions_new_linkageerror(message,NULL);
-       MFREE(message,char,msglen);
-       return false; /* exception */
+       /* check succeeds */
+       return resolveSucceeded;
 }
-
-#endif /* ENABLE_VERIFIER */
+#endif /* defined(ENABLE_VERIFIER) */
 
 /******************************************************************************/
 /* CLASS RESOLUTION                                                           */
@@ -635,7 +879,7 @@ bool resolve_class(unresolved_class *ref,
                                   classinfo **result)
 {
        classinfo *cls;
-       bool checked;
+       resolve_result_t checkresult;
        
        assert(ref);
        assert(result);
@@ -644,7 +888,7 @@ bool resolve_class(unresolved_class *ref,
        *result = NULL;
 
 #ifdef RESOLVE_VERBOSE
-       unresolved_class_debug_dump(ref,stderr);
+       unresolved_class_debug_dump(ref,stdout);
 #endif
 
        /* first we must resolve the class */
@@ -661,17 +905,14 @@ bool resolve_class(unresolved_class *ref,
        assert((cls->state & CLASS_LOADED) && (cls->state & CLASS_LINKED));
 
        /* now we check the subtype constraints */
-       if (!resolve_and_check_subtype_set(ref->classref->referer,ref->referermethod,
+       
+       checkresult = resolve_and_check_subtype_set(ref->referermethod,
                                                                           &(ref->subtypeconstraints),
                                                                           CLASSREF_OR_CLASSINFO(cls),
-                                                                          false,
                                                                           mode,
-                                                                          resolveLinkageError,&checked))
-       {
-               return false; /* exception */
-       }
-       if (!checked)
-               return true; /* be lazy */
+                                                                          resolveLinkageError);
+       if (checkresult != resolveSucceeded)
+               return (bool) checkresult;
 
        /* succeed */
        *result = cls;
@@ -728,7 +969,7 @@ classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
        /* ensure that the class is not abstract */
 
        if (c->flags & ACC_ABSTRACT) {
-               *exceptionptr = new_verifyerror(NULL,"creating instance of abstract class");
+               exceptions_throw_verifyerror(NULL,"creating instance of abstract class");
                return NULL;
        }
 
@@ -761,45 +1002,342 @@ classinfo * resolve_class_eager(unresolved_class *ref)
 }
 #endif /* ENABLE_VERIFIER */
 
-/******************************************************************************/
-/* FIELD RESOLUTION                                                           */
-/******************************************************************************/
-
-/* resolve_field ***************************************************************
+/* resolve_class_eager_no_access_check *****************************************
  
-   Resolve an unresolved field reference
+   Resolve an unresolved class reference eagerly. The class is also linked.
+   Access rights are _not_ checked.
   
    IN:
        ref..............struct containing the reference
-       mode.............mode of resolution:
-                            resolveLazy...only resolve if it does not
-                                          require loading classes
-                            resolveEager..load classes if necessary
-  
-   OUT:
-       *result..........set to the result of resolution, or to NULL if
-                        the reference has not been resolved
-                        In the case of an exception, *result is
-                        guaranteed to be set to NULL.
-  
+   
    RETURN VALUE:
-       true.............everything ok 
-                        (*result may still be NULL for resolveLazy)
-       false............an exception has been thrown
+       classinfo * to the class, or
+          NULL if an exception has been thrown
    
 *******************************************************************************/
 
-bool resolve_field(unresolved_field *ref,
-                                  resolve_mode_t mode,
-                                  fieldinfo **result)
+#ifdef ENABLE_VERIFIER
+classinfo * resolve_class_eager_no_access_check(unresolved_class *ref)
+{
+       classinfo *c;
+
+       if (!resolve_class(ref, resolveEager, false, &c))
+               return NULL;
+
+       return c;
+}
+#endif /* ENABLE_VERIFIER */
+
+/******************************************************************************/
+/* FIELD RESOLUTION                                                           */
+/******************************************************************************/
+
+/* resolve_field_verifier_checks *******************************************
+   Do the verifier checks necessary after field has been resolved.
+  
+   IN:
+       refmethod........the method containing the reference
+          fieldref.........the field reference
+          container........the class where the field was found
+          fi...............the fieldinfo of the resolved field
+          instanceti.......instance typeinfo, if available
+          valueti..........value typeinfo, if available
+          isstatic.........true if this is a *STATIC* instruction
+          isput............true if this is a PUT* instruction
+  
+   RETURN VALUE:
+       resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+       resolveFailed.......exception has been thrown
+   
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
+                                                                                          constant_FMIref *fieldref,
+                                                                                          classinfo *container,
+                                                                                          fieldinfo *fi,
+                                                                                          typeinfo *instanceti,
+                                                                                          typeinfo *valueti,
+                                                                                          bool isstatic,
+                                                                                          bool isput)
+{
+       classinfo         *declarer;
+       classinfo         *referer;
+       resolve_result_t   result;
+       constant_classref *fieldtyperef;
+       char              *msg;
+       s4                 msglen;
+       utf               *u;
+
+       assert(refmethod);
+       assert(fieldref);
+       assert(container);
+       assert(fi);
+
+       /* get the classinfos and the field type */
+
+       referer = refmethod->class;
+       assert(referer);
+
+       declarer = fi->class;
+       assert(declarer);
+       assert(referer->state & CLASS_LINKED);
+
+       fieldtyperef = fieldref->parseddesc.fd->classref;
+
+       /* check static */
+
+#if true != 1
+#error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
+#endif
+
+       if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
+               /* a static field is accessed via an instance, or vice versa */
+               exceptions_throw_incompatibleclasschangeerror(declarer,
+                                                                                                         (fi->flags & ACC_STATIC)
+                                                                                                         ? "static field accessed via instance"
+                                                                                                         : "instance field  accessed without instance");
+
+               return resolveFailed;
+       }
+
+       /* check access rights */
+
+       if (!access_is_accessible_member(referer,declarer,fi->flags)) {
+               msglen =
+                       utf_bytes(declarer->name) +
+                       utf_bytes(fi->name) +
+                       utf_bytes(referer->name) +
+                       100;
+
+               msg = MNEW(char, msglen);
+
+               strcpy(msg, "field is not accessible (");
+               utf_cat_classname(msg, declarer->name);
+               strcat(msg, ".");
+               utf_cat(msg, fi->name);
+               strcat(msg, " from ");
+               utf_cat_classname(msg, referer->name);
+               strcat(msg, ")");
+
+               u = utf_new_char(msg);
+
+               MFREE(msg, char, msglen);
+
+               exceptions_throw_illegalaccessexception(u);
+
+               return resolveFailed; /* exception */
+       }
+
+       /* for non-static methods we have to check the constraints on the         */
+       /* instance type                                                          */
+
+       if (instanceti) {
+               typeinfo *insttip;
+               typeinfo tinfo;
+
+               /* The instanceslot must contain a reference to a non-array type */
+
+               if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
+                       return resolveFailed;
+               }
+               if (TYPEINFO_IS_ARRAY(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
+                       return resolveFailed;
+               }
+
+               if (isput && TYPEINFO_IS_NEWOBJECT(*instanceti))
+               {
+                       /* The instruction writes a field in an uninitialized object. */
+                       /* This is only allowed when a field of an uninitialized 'this' object is */
+                       /* written inside an initialization method                                */
+
+                       classinfo *initclass;
+                       instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+
+                       if (ins != NULL) {
+                               exceptions_throw_verifyerror(refmethod, "accessing field of uninitialized object");
+                               return resolveFailed;
+                       }
+
+                       /* XXX check that class of field == refmethod->class */
+                       initclass = referer; /* XXX classrefs */
+                       assert(initclass->state & CLASS_LINKED);
+
+                       typeinfo_init_classinfo(&tinfo, initclass);
+                       insttip = &tinfo;
+               }
+               else {
+                       insttip = instanceti;
+               }
+
+               result = resolve_lazy_subtype_checks(refmethod,
+                               insttip,
+                               CLASSREF_OR_CLASSINFO(container),
+                               resolveLinkageError);
+               if (result != resolveSucceeded)
+                       return result;
+
+               /* check protected access */
+
+               if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
+               {
+                       result = resolve_lazy_subtype_checks(refmethod,
+                                       instanceti,
+                                       CLASSREF_OR_CLASSINFO(referer),
+                                       resolveIllegalAccessError);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+
+       }
+
+       /* for PUT* instructions we have to check the constraints on the value type */
+
+       if (valueti) {
+               assert(fieldtyperef);
+
+               /* check subtype constraints */
+               result = resolve_lazy_subtype_checks(refmethod,
+                               valueti,
+                               CLASSREF_OR_CLASSINFO(fieldtyperef),
+                               resolveLinkageError);
+
+               if (result != resolveSucceeded)
+                       return result;
+       }
+
+       /* impose loading constraint on field type */
+
+       if (fi->type == TYPE_ADR) {
+               assert(fieldtyperef);
+               if (!classcache_add_constraint(declarer->classloader,
+                                                                          referer->classloader,
+                                                                          fieldtyperef->name))
+                       return resolveFailed;
+       }
+
+       /* XXX impose loading constraint on instance? */
+
+       /* everything ok */
+       return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/* resolve_field_lazy **********************************************************
+   Resolve an unresolved field reference lazily
+
+   NOTE: This function does NOT do any verification checks. In case of a
+         successful resolution, you must call resolve_field_verifier_checks
+                in order to perform the necessary checks!
+  
+   IN:
+          refmethod........the referer method
+          fieldref.........the field reference
+  
+   RETURN VALUE:
+       resolveSucceeded.....the reference has been resolved
+       resolveDeferred......the resolving could not be performed lazily
+          resolveFailed........resolving failed, an exception has been thrown.
+   
+*******************************************************************************/
+
+resolve_result_t resolve_field_lazy(methodinfo *refmethod,
+                                                                       constant_FMIref *fieldref)
+{
+       classinfo *referer;
+       classinfo *container;
+       fieldinfo *fi;
+
+       assert(refmethod);
+
+       /* the class containing the reference */
+
+       referer = refmethod->class;
+       assert(referer);
+
+       /* check if the field itself is already resolved */
+
+       if (IS_FMIREF_RESOLVED(fieldref))
+               return resolveSucceeded;
+
+       /* first we must resolve the class containg the field */
+
+       /* XXX can/may lazyResolving trigger linking? */
+
+       if (!resolve_class_from_name(referer, refmethod,
+                  fieldref->p.classref->name, resolveLazy, true, true, &container))
+       {
+               /* the class reference could not be resolved */
+               return resolveFailed; /* exception */
+       }
+       if (!container)
+               return resolveDeferred; /* be lazy */
+
+       assert(container->state & CLASS_LINKED);
+
+       /* now we must find the declaration of the field in `container`
+        * or one of its superclasses */
+
+       fi = class_resolvefield(container,
+                                                       fieldref->name, fieldref->descriptor,
+                                                       referer, true);
+       if (!fi) {
+               /* The field does not exist. But since we were called lazily, */
+               /* this error must not be reported now. (It will be reported   */
+               /* if eager resolving of this field is ever tried.)           */
+
+               exceptions_clear_exception();
+               return resolveDeferred; /* be lazy */
+       }
+
+       /* cache the result of the resolution */
+
+       fieldref->p.field = fi;
+
+       /* everything ok */
+       return resolveSucceeded;
+}
+
+/* resolve_field ***************************************************************
+   Resolve an unresolved field reference
+  
+   IN:
+       ref..............struct containing the reference
+       mode.............mode of resolution:
+                            resolveLazy...only resolve if it does not
+                                          require loading classes
+                            resolveEager..load classes if necessary
+  
+   OUT:
+       *result..........set to the result of resolution, or to NULL if
+                        the reference has not been resolved
+                        In the case of an exception, *result is
+                        guaranteed to be set to NULL.
+  
+   RETURN VALUE:
+       true.............everything ok 
+                        (*result may still be NULL for resolveLazy)
+       false............an exception has been thrown
+   
+*******************************************************************************/
+
+bool resolve_field(unresolved_field *ref,
+                                  resolve_mode_t mode,
+                                  fieldinfo **result)
 {
        classinfo *referer;
        classinfo *container;
        classinfo *declarer;
        constant_classref *fieldtyperef;
        fieldinfo *fi;
-       bool checked;
-       
+       resolve_result_t checkresult;
+
        assert(ref);
        assert(result);
        assert(mode == resolveLazy || mode == resolveEager);
@@ -807,17 +1345,24 @@ bool resolve_field(unresolved_field *ref,
        *result = NULL;
 
 #ifdef RESOLVE_VERBOSE
-       unresolved_field_debug_dump(ref,stderr);
+       unresolved_field_debug_dump(ref,stdout);
 #endif
 
        /* the class containing the reference */
 
-       referer = ref->fieldref->classref->referer;
+       referer = ref->referermethod->class;
        assert(referer);
 
+       /* check if the field itself is already resolved */
+       if (IS_FMIREF_RESOLVED(ref->fieldref)) {
+               fi = ref->fieldref->p.field;
+               container = fi->class;
+               goto resolved_the_field;
+       }
+
        /* first we must resolve the class containg the field */
        if (!resolve_class_from_name(referer,ref->referermethod,
-                                          ref->fieldref->classref->name,mode,true,true,&container))
+                                          ref->fieldref->p.classref->name,mode,true,true,&container))
        {
                /* the class reference could not be resolved */
                return false; /* exception */
@@ -833,7 +1378,7 @@ bool resolve_field(unresolved_field *ref,
         * or one of its superclasses */
 
 #ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"    resolving field in class...\n");
+               printf("    resolving field in class...\n");
 #endif
 
        fi = class_resolvefield(container,
@@ -845,148 +1390,83 @@ bool resolve_field(unresolved_field *ref,
                        /* this error must not be reported now. (It will be reported   */
                        /* if eager resolving of this field is ever tried.)           */
 
-                       *exceptionptr = NULL;
+                       exceptions_clear_exception();
                        return true; /* be lazy */
                }
-               
-               return false; /* exception */
-       }
-
-#ifdef ENABLE_VERIFIER
-
-       /* { the field reference has been resolved } */
-       declarer = fi->class;
-       assert(declarer);
-       assert(declarer->state & CLASS_LOADED);
-       assert(declarer->state & CLASS_LINKED);
-
-#ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"    checking static...\n");
-#endif
 
-       /* check static */
-
-       if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
-               /* a static field is accessed via an instance, or vice versa */
-               *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
-                               (fi->flags & ACC_STATIC) ? "static field accessed via instance"
-                                                        : "instance field accessed without instance");
                return false; /* exception */
        }
 
-       /* for non-static accesses we have to check the constraints on the */
-       /* instance type */
+       /* cache the result of the resolution */
+       ref->fieldref->p.field = fi;
 
-       if (!(ref->flags & RESOLVE_STATIC)) {
-#ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"    checking instance types...\n");
-#endif
+resolved_the_field:
 
-               if (!resolve_and_check_subtype_set(referer,ref->referermethod,
-                                                                                  &(ref->instancetypes),
-                                                                                  CLASSREF_OR_CLASSINFO(container),
-                                                                                  false, mode, resolveLinkageError,
-                                                                                  &checked))
-               {
-                       return false; /* exception */
+#ifdef ENABLE_VERIFIER
+       /* Checking opt_verify is ok here, because the NULL iptr guarantees */
+       /* that no missing parts of an instruction will be accessed.        */
+       if (opt_verify) {
+               checkresult = resolve_field_verifier_checks(
+                               ref->referermethod,
+                               ref->fieldref,
+                               container,
+                               fi,
+                               NULL, /* instanceti, handled by constraints below */
+                               NULL, /* valueti, handled by constraints below  */
+                               (ref->flags & RESOLVE_STATIC) != 0, /* isstatic */
+                               (ref->flags & RESOLVE_PUTFIELD) != 0 /* isput */);
+
+               if (checkresult != resolveSucceeded)
+                       return (bool) checkresult;
+
+               declarer = fi->class;
+               assert(declarer);
+               assert(declarer->state & CLASS_LOADED);
+               assert(declarer->state & CLASS_LINKED);
+
+               /* for non-static accesses we have to check the constraints on the */
+               /* instance type */
+
+               if (!(ref->flags & RESOLVE_STATIC)) {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(container),
+                                       mode, resolveLinkageError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
                }
 
-               if (!checked)
-                       return true; /* be lazy */
-       }
-
-#ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    checking instance types...done\n");
-#endif
-
-       fieldtyperef = ref->fieldref->parseddesc.fd->classref;
-
-       /* for PUT* instructions we have to check the constraints on the value type */
-       if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
-#ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"    checking value constraints...\n");
-#endif
-               assert(fieldtyperef);
-               if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
-                       /* check subtype constraints */
-                       if (!resolve_and_check_subtype_set(referer, ref->referermethod,
-                                                                                          &(ref->valueconstraints),
-                                                                                          CLASSREF_OR_CLASSINFO(fieldtyperef),
-                                                                                          false, mode, resolveLinkageError,
-                                                                                          &checked))
-                       {
-                               return false; /* exception */
+               fieldtyperef = ref->fieldref->parseddesc.fd->classref;
+
+               /* for PUT* instructions we have to check the constraints on the value type */
+               if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
+                       assert(fieldtyperef);
+                       if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
+                               /* check subtype constraints */
+                               checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                               &(ref->valueconstraints),
+                                               CLASSREF_OR_CLASSINFO(fieldtyperef),
+                                               mode, resolveLinkageError);
+                               if (checkresult != resolveSucceeded)
+                                       return (bool) checkresult;
                        }
-                       if (!checked)
-                               return true; /* be lazy */
                }
-       }
-                                                                          
-       /* check access rights */
-#ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    checking access rights...\n");
-#endif
-       if (!access_is_accessible_member(referer,declarer,fi->flags)) {
-               int msglen;
-               char *message;
-
-               msglen = utf_strlen(declarer->name) + utf_strlen(fi->name) + utf_strlen(referer->name) + 100;
-               message = MNEW(char,msglen);
-               strcpy(message,"field is not accessible (");
-               utf_sprint_classname(message+strlen(message),declarer->name);
-               strcat(message,".");
-               utf_sprint(message+strlen(message),fi->name);
-               strcat(message," from ");
-               utf_sprint_classname(message+strlen(message),referer->name);
-               strcat(message,")");
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
-               MFREE(message,char,msglen);
-               return false; /* exception */
-       }
-#ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    checking access rights...done\n");
-       fprintf(stderr,"        declarer = ");
-       utf_fprint_classname(stderr,declarer->name); fputc('\n',stderr);
-       fprintf(stderr,"        referer = ");
-       utf_fprint_classname(stderr,referer->name); fputc('\n',stderr);
-#endif
 
-       /* check protected access */
-       if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
-#ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"    checking protected access...\n");
-#endif
-               if (!resolve_and_check_subtype_set(referer,ref->referermethod,
-                                                                                  &(ref->instancetypes),
-                                                                                  CLASSREF_OR_CLASSINFO(referer),
-                                                                                  false, mode,
-                                                                                  resolveIllegalAccessError, &checked))
-               {
-                       return false; /* exception */
+               /* check protected access */
+               if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(referer),
+                                       mode,
+                                       resolveIllegalAccessError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
                }
 
-               if (!checked)
-                       return true; /* be lazy */
-       }
-
-       /* impose loading constraint on field type */
-
-       if (fi->type == TYPE_ADR) {
-#ifdef RESOLVE_VERBOSE
-               fprintf(stderr,"    adding constraint...\n");
-#endif
-               assert(fieldtyperef);
-               if (!classcache_add_constraint(declarer->classloader,
-                                                                          referer->classloader,
-                                                                          fieldtyperef->name))
-                       return false;
        }
 #endif /* ENABLE_VERIFIER */
 
        /* succeed */
-#ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    success.\n");
-#endif
        *result = fi;
 
        return true;
@@ -1012,12 +1492,549 @@ fieldinfo * resolve_field_eager(unresolved_field *ref)
        if (!resolve_field(ref,resolveEager,&fi))
                return NULL;
 
-       return fi;
-}
+       return fi;
+}
+
+/******************************************************************************/
+/* METHOD RESOLUTION                                                          */
+/******************************************************************************/
+
+/* resolve_method_invokespecial_lookup *****************************************
+   Do the special lookup for methods invoked by INVOKESPECIAL
+  
+   IN:
+       refmethod........the method containing the reference
+          mi...............the methodinfo of the resolved method
+  
+   RETURN VALUE:
+       a methodinfo *...the result of the lookup,
+          NULL.............an exception has been thrown
+   
+*******************************************************************************/
+
+methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
+                                                                                                methodinfo *mi)
+{
+       classinfo *declarer;
+       classinfo *referer;
+
+       assert(refmethod);
+       assert(mi);
+
+       /* get referer and declarer classes */
+
+       referer = refmethod->class;
+       assert(referer);
+
+       declarer = mi->class;
+       assert(declarer);
+       assert(referer->state & CLASS_LINKED);
+
+       /* checks for INVOKESPECIAL:                                       */
+       /* for <init> and methods of the current class we don't need any   */
+       /* special checks. Otherwise we must verify that the called method */
+       /* belongs to a super class of the current class                   */
+
+       if ((referer != declarer) && (mi->name != utf_init)) {
+               /* check that declarer is a super class of the current class   */
+
+               if (!class_issubclass(referer,declarer)) {
+                       exceptions_throw_verifyerror(refmethod,
+                                       "INVOKESPECIAL calling non-super class method");
+                       return NULL;
+               }
+
+               /* if the referer has ACC_SUPER set, we must do the special    */
+               /* lookup starting with the direct super class of referer      */
+
+               if ((referer->flags & ACC_SUPER) != 0) {
+                       mi = class_resolvemethod(referer->super.cls,
+                                                                        mi->name,
+                                                                        mi->descriptor);
+
+                       if (mi == NULL) {
+                               /* the spec calls for an AbstractMethodError in this case */
+
+                               exceptions_throw_abstractmethoderror();
+
+                               return NULL;
+                       }
+               }
+       }
+
+       /* everything ok */
+       return mi;
+}
+
+/* resolve_method_verifier_checks ******************************************
+   Do the verifier checks necessary after a method has been resolved.
+  
+   IN:
+       refmethod........the method containing the reference
+          methodref........the method reference
+          mi...............the methodinfo of the resolved method
+          invokestatic.....true if the method is invoked by INVOKESTATIC
+  
+   RETURN VALUE:
+       resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+       resolveFailed.......exception has been thrown
+   
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
+                                                                                               constant_FMIref *methodref,
+                                                                                               methodinfo *mi,
+                                                                                               bool invokestatic)
+{
+       classinfo *declarer;
+       classinfo *referer;
+       char      *msg;
+       s4         msglen;
+       utf       *u;
+
+       assert(refmethod);
+       assert(methodref);
+       assert(mi);
+
+#ifdef RESOLVE_VERBOSE
+       printf("resolve_method_verifier_checks\n");
+       printf("    flags: %02x\n",mi->flags);
+#endif
+
+       /* get the classinfos and the method descriptor */
+
+       referer = refmethod->class;
+       assert(referer);
+
+       declarer = mi->class;
+       assert(declarer);
+
+       /* check static */
+
+       if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
+               /* a static method is accessed via an instance, or vice versa */
+               exceptions_throw_incompatibleclasschangeerror(declarer,
+                                                                                                         (mi->flags & ACC_STATIC)
+                                                                                                         ? "static method called via instance"
+                                                                                                         : "instance method called without instance");
+
+               return resolveFailed;
+       }
+
+       /* check access rights */
+
+       if (!access_is_accessible_member(referer,declarer,mi->flags)) {
+               /* XXX clean this up. this should be in exceptions.c */
+
+               msglen =
+                       utf_bytes(declarer->name) +
+                       utf_bytes(mi->name) +
+                       utf_bytes(mi->descriptor) +
+                       utf_bytes(referer->name) +
+                       100;
+
+               msg = MNEW(char, msglen);
+
+               strcpy(msg, "method is not accessible (");
+               utf_cat_classname(msg, declarer->name);
+               strcat(msg, ".");
+               utf_cat(msg, mi->name);
+               utf_cat(msg, mi->descriptor);
+               strcat(msg, " from ");
+               utf_cat_classname(msg, referer->name);
+               strcat(msg, ")");
+
+               u = utf_new_char(msg);
+
+               MFREE(msg, char, msglen);
+
+               exceptions_throw_illegalaccessexception(u);
+
+               return resolveFailed; /* exception */
+       }
+
+       /* everything ok */
+
+       return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_instance_type_checks *****************************************
+
+   Check the instance type of a method invocation.
+
+   IN:
+       refmethod........the method containing the reference
+          mi...............the methodinfo of the resolved method
+          instanceti.......typeinfo of the instance slot
+          invokespecial....true if the method is invoked by INVOKESPECIAL
+
+   RETURN VALUE:
+       resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+       resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
+                                                                                                        methodinfo *mi,
+                                                                                                        typeinfo *instanceti,
+                                                                                                        bool invokespecial)
+{
+       typeinfo         tinfo;
+       typeinfo        *tip;
+       resolve_result_t result;
+
+       if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
+       {   /* XXX clean up */
+               instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+               classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
+                                                                        : CLASSREF_OR_CLASSINFO(refmethod->class);
+               tip = &tinfo;
+               if (!typeinfo_init_class(tip, initclass))
+                       return false;
+       }
+       else {
+               tip = instanceti;
+       }
+
+       result = resolve_lazy_subtype_checks(refmethod,
+                                                                                tip,
+                                                                                CLASSREF_OR_CLASSINFO(mi->class),
+                                                                                resolveLinkageError);
+       if (result != resolveSucceeded)
+               return result;
+
+       /* check protected access */
+
+       /* XXX use other `declarer` than mi->class? */
+       if (((mi->flags & ACC_PROTECTED) != 0)
+                       && !SAME_PACKAGE(mi->class, refmethod->class))
+       {
+               result = resolve_lazy_subtype_checks(refmethod,
+                               tip,
+                               CLASSREF_OR_CLASSINFO(refmethod->class),
+                               resolveIllegalAccessError);
+               if (result != resolveSucceeded)
+                       return result;
+       }
+
+       /* everything ok */
+
+       return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_param_type_checks ********************************************
+
+   Check non-instance parameter types of a method invocation.
+
+   IN:
+          jd...............jitdata of the method doing the call
+       refmethod........the method containing the reference
+          iptr.............the invoke instruction
+          mi...............the methodinfo of the resolved method
+          invokestatic.....true if the method is invoked by INVOKESTATIC
+
+   RETURN VALUE:
+       resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+       resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_param_type_checks(jitdata *jd, 
+                                                                                                 methodinfo *refmethod,
+                                                                                                 instruction *iptr, 
+                                                                                                 methodinfo *mi,
+                                                                                                 bool invokestatic)
+{
+       varinfo         *param;
+       resolve_result_t result;
+       methoddesc      *md;
+       typedesc        *paramtypes;
+       s4               type;
+       s4               instancecount;
+       s4               i;
+
+       assert(jd);
+
+       instancecount = (invokestatic) ? 0 : 1;
+
+       /* check subtype constraints for TYPE_ADR parameters */
+
+       md = mi->parseddesc;
+       paramtypes = md->paramtypes;
+
+       for (i = md->paramcount-1-instancecount; i>=0; --i) {
+               param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+               type = md->paramtypes[i+instancecount].type;
+
+               assert(param);
+               assert(type == param->type);
+
+               if (type == TYPE_ADR) {
+                       result = resolve_lazy_subtype_checks(refmethod,
+                                       &(param->typeinfo),
+                                       CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
+                                       resolveLinkageError);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+       }
+
+       /* everything ok */
+
+       return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_param_type_checks_stackbased *********************************
+
+   Check non-instance parameter types of a method invocation.
+
+   IN:
+       refmethod........the method containing the reference
+          mi...............the methodinfo of the resolved method
+          invokestatic.....true if the method is invoked by INVOKESTATIC
+          stack............TOS before the INVOKE instruction
+
+   RETURN VALUE:
+       resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+       resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_param_type_checks_stackbased(
+               methodinfo *refmethod, 
+               methodinfo *mi,
+               bool invokestatic, 
+               typedescriptor *stack)
+{
+       typedescriptor  *param;
+       resolve_result_t result;
+       methoddesc      *md;
+       typedesc        *paramtypes;
+       s4               type;
+       s4               instancecount;
+       s4               i;
+
+       instancecount = (invokestatic) ? 0 : 1;
+
+       /* check subtype constraints for TYPE_ADR parameters */
+
+       md = mi->parseddesc;
+       paramtypes = md->paramtypes;
+
+       param = stack - (md->paramslots - 1 - instancecount);
+
+       for (i = instancecount; i < md->paramcount; ++i) {
+               type = md->paramtypes[i].type;
+
+               assert(type == param->type);
+
+               if (type == TYPE_ADR) {
+                       result = resolve_lazy_subtype_checks(refmethod,
+                                       &(param->typeinfo),
+                                       CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
+                                       resolveLinkageError);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+
+               param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
+       }
+
+       /* everything ok */
+
+       return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_loading_constraints ******************************************
+
+   Impose loading constraints on the parameters and return type of the
+   given method.
+
+   IN:
+       referer..........the class refering to the method
+          mi...............the method
+
+   RETURN VALUE:
+       true................everything ok
+          false...............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_method_loading_constraints(classinfo *referer,
+                                                                               methodinfo *mi)
+{
+       methoddesc *md;
+       typedesc   *paramtypes;
+       utf        *name;
+       s4          i;
+       s4          instancecount;
+
+       /* impose loading constraints on parameters (including instance) */
+
+       md = mi->parseddesc;
+       paramtypes = md->paramtypes;
+       instancecount = (mi->flags & ACC_STATIC) / ACC_STATIC;
+
+       for (i = 0; i < md->paramcount; i++) {
+               if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
+                       if (i < instancecount) {
+                               /* The type of the 'this' pointer is the class containing */
+                               /* the method definition. Since container is the same as, */
+                               /* or a subclass of declarer, we also constrain declarer  */
+                               /* by transitivity of loading constraints.                */
+                               name = mi->class->name;
+                       }
+                       else {
+                               name = paramtypes[i].classref->name;
+                       }
+
+                       /* The caller (referer) and the callee (container) must agree */
+                       /* on the types of the parameters.                            */
+                       if (!classcache_add_constraint(referer->classloader,
+                                                                                  mi->class->classloader, name))
+                               return false; /* exception */
+               }
+       }
+
+       /* impose loading constraint onto return type */
+
+       if (md->returntype.type == TYPE_ADR) {
+               /* The caller (referer) and the callee (container) must agree */
+               /* on the return type.                                        */
+               if (!classcache_add_constraint(referer->classloader,
+                                       mi->class->classloader,
+                                       md->returntype.classref->name))
+                       return false; /* exception */
+       }
+
+       /* everything ok */
+
+       return true;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_lazy *********************************************************
+   Resolve an unresolved method reference lazily
+  
+   NOTE: This function does NOT do any verification checks. In case of a
+         successful resolution, you must call resolve_method_verifier_checks
+                in order to perform the necessary checks!
+  
+   IN:
+          refmethod........the referer method
+          methodref........the method reference
+          invokespecial....true if this is an INVOKESPECIAL instruction
+  
+   RETURN VALUE:
+       resolveSucceeded.....the reference has been resolved
+       resolveDeferred......the resolving could not be performed lazily
+          resolveFailed........resolving failed, an exception has been thrown.
+   
+*******************************************************************************/
+
+resolve_result_t resolve_method_lazy(methodinfo *refmethod,
+                                                                        constant_FMIref *methodref,
+                                                                        bool invokespecial)
+{
+       classinfo *referer;
+       classinfo *container;
+       methodinfo *mi;
+
+       assert(refmethod);
+
+#ifdef RESOLVE_VERBOSE
+       printf("resolve_method_lazy\n");
+#endif
+
+       /* the class containing the reference */
+
+       referer = refmethod->class;
+       assert(referer);
+
+       /* check if the method itself is already resolved */
+
+       if (IS_FMIREF_RESOLVED(methodref))
+               return resolveSucceeded;
+
+       /* first we must resolve the class containg the method */
+
+       if (!resolve_class_from_name(referer, refmethod,
+                  methodref->p.classref->name, resolveLazy, true, true, &container))
+       {
+               /* the class reference could not be resolved */
+               return resolveFailed; /* exception */
+       }
+       if (!container)
+               return resolveDeferred; /* be lazy */
+
+       assert(container->state & CLASS_LINKED);
+
+       /* now we must find the declaration of the method in `container`
+        * or one of its superclasses */
+
+       if (container->flags & ACC_INTERFACE) {
+               mi = class_resolveinterfacemethod(container,
+                                                                             methodref->name,
+                                                                                 methodref->descriptor,
+                                                                             referer, true);
+
+       } else {
+               mi = class_resolveclassmethod(container,
+                                                                         methodref->name,
+                                                                         methodref->descriptor,
+                                                                         referer, true);
+       }
+
+       if (!mi) {
+               /* The method does not exist. But since we were called lazily, */
+               /* this error must not be reported now. (It will be reported   */
+               /* if eager resolving of this method is ever tried.)           */
+
+               exceptions_clear_exception();
+               return resolveDeferred; /* be lazy */
+       }
+
+       if (invokespecial) {
+               mi = resolve_method_invokespecial_lookup(refmethod, mi);
+               if (!mi)
+                       return resolveFailed; /* exception */
+       }
+
+       /* have the method params already been parsed? no, do it. */
+
+       if (!mi->parseddesc->params)
+               if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
+                       return resolveFailed;
+
+       /* cache the result of the resolution */
+
+       methodref->p.method = mi;
+
+       /* succeed */
 
-/******************************************************************************/
-/* METHOD RESOLUTION                                                          */
-/******************************************************************************/
+       return resolveSucceeded;
+}
 
 /* resolve_method **************************************************************
  
@@ -1052,25 +2069,35 @@ bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **re
        typedesc *paramtypes;
        int instancecount;
        int i;
-       bool checked;
-       
+       resolve_result_t checkresult;
+
        assert(ref);
        assert(result);
        assert(mode == resolveLazy || mode == resolveEager);
 
 #ifdef RESOLVE_VERBOSE
-       unresolved_method_debug_dump(ref,stderr);
+       unresolved_method_debug_dump(ref,stdout);
 #endif
 
        *result = NULL;
 
        /* the class containing the reference */
-       referer = ref->methodref->classref->referer;
+
+       referer = ref->referermethod->class;
        assert(referer);
 
-       /* first we must resolve the class containg the method */
+       /* check if the method itself is already resolved */
+
+       if (IS_FMIREF_RESOLVED(ref->methodref)) {
+               mi = ref->methodref->p.method;
+               container = mi->class;
+               goto resolved_the_method;
+       }
+
+       /* first we must resolve the class containing the method */
+
        if (!resolve_class_from_name(referer,ref->referermethod,
-                                          ref->methodref->classref->name,mode,true,true,&container))
+                                          ref->methodref->p.classref->name,mode,true,true,&container))
        {
                /* the class reference could not be resolved */
                return false; /* exception */
@@ -1103,63 +2130,19 @@ bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **re
                        /* this error must not be reported now. (It will be reported   */
                        /* if eager resolving of this method is ever tried.)           */
 
-                       *exceptionptr = NULL;
+                       exceptions_clear_exception();
                        return true; /* be lazy */
                }
-               
+
                return false; /* exception */ /* XXX set exceptionptr? */
        }
 
-#ifdef ENABLE_VERIFIER
-
-#ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    flags: %02x\n",mi->flags);
-#endif
        /* { the method reference has been resolved } */
 
-       declarer = mi->class;
-       assert(declarer);
-       assert(referer->state & CLASS_LINKED);
-
-       /* checks for INVOKESPECIAL:                                       */
-       /* for <init> and methods of the current class we don't need any   */
-       /* special checks. Otherwise we must verify that the called method */
-       /* belongs to a super class of the current class                   */
-       if (((ref->flags & RESOLVE_SPECIAL) != 0) 
-               && referer != declarer 
-               && mi->name != utf_init) 
-       {
-               /* check that declarer is a super class of the current class   */
-               if (!class_issubclass(referer,declarer)) {
-                       *exceptionptr = new_verifyerror(ref->referermethod,
-                                       "INVOKESPECIAL calling non-super class method");
-                       return false;
-               }
-
-               /* if the referer has ACC_SUPER set, we must do the special    */
-               /* lookup starting with the direct super class of referer      */
-               if ((referer->flags & ACC_SUPER) != 0) {
-                       mi = class_resolvemethod(referer->super.cls,
-                                                                        ref->methodref->name,
-                                                                        ref->methodref->descriptor);
-                       if (!mi) {
-                               /* the spec calls for an AbstractMethodError in this case */
-                               *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
-                               return false;
-                       }
-                       declarer = mi->class;
-               }
-       }
-
-       /* check static */
-
-       if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
-               /* a static method is accessed via an instance, or vice versa */
-               *exceptionptr =
-                       new_exception_message(string_java_lang_IncompatibleClassChangeError,
-                               (mi->flags & ACC_STATIC) ? "static method called via instance"
-                                                        : "instance method called without instance");
-               return false;
+       if (ref->flags & RESOLVE_SPECIAL) {
+               mi = resolve_method_invokespecial_lookup(ref->referermethod,mi);
+               if (!mi)
+                       return false; /* exception */
        }
 
        /* have the method params already been parsed? no, do it. */
@@ -1167,127 +2150,83 @@ bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **re
        if (!mi->parseddesc->params)
                if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
                        return false;
-               
-       /* for non-static methods we have to check the constraints on the         */
-       /* instance type                                                          */
 
-       if (!(ref->flags & RESOLVE_STATIC)) {
-               if (!resolve_and_check_subtype_set(referer,ref->referermethod,
-                                                                                  &(ref->instancetypes),
-                                                                                  CLASSREF_OR_CLASSINFO(container),
-                                                                                  false,
-                                                                                  mode,
-                                                                                  resolveLinkageError,&checked))
-               {
-                       return false; /* exception */
-               }
-               if (!checked)
-                       return true; /* be lazy */
-               instancecount = 1;
-       }
-       else {
-               instancecount = 0;
-       }
+       /* cache the resolution */
 
-       /* check subtype constraints for TYPE_ADR parameters */
+       ref->methodref->p.method = mi;
 
-       assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
-       paramtypes = mi->parseddesc->paramtypes;
-       
-       for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
-               if (paramtypes[i+instancecount].type == TYPE_ADR) {
-                       if (ref->paramconstraints) {
-                               if (!resolve_and_check_subtype_set(referer,ref->referermethod,
-                                                       ref->paramconstraints + i,
-                                                       CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
-                                                       false,
-                                                       mode,
-                                                       resolveLinkageError,&checked))
-                               {
-                                       return false; /* exception */
-                               }
-                               if (!checked)
-                                       return true; /* be lazy */
-                       }
-               }
-       }
+resolved_the_method:
 
-       /* check access rights */
+#ifdef ENABLE_VERIFIER
+       if (opt_verify) {
 
-       if (!access_is_accessible_member(referer,declarer,mi->flags)) {
-               int msglen;
-               char *message;
-
-               msglen = utf_strlen(declarer->name) + utf_strlen(mi->name) + 
-                       utf_strlen(mi->descriptor) + utf_strlen(referer->name) + 100;
-               message = MNEW(char,msglen);
-               strcpy(message,"method is not accessible (");
-               utf_sprint_classname(message+strlen(message),declarer->name);
-               strcat(message,".");
-               utf_sprint(message+strlen(message),mi->name);
-               utf_sprint(message+strlen(message),mi->descriptor);
-               strcat(message," from ");
-               utf_sprint_classname(message+strlen(message),referer->name);
-               strcat(message,")");
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
-               MFREE(message,char,msglen);
-               return false; /* exception */
-       }
+               checkresult = resolve_method_verifier_checks(
+                               ref->referermethod,
+                               ref->methodref,
+                               mi,
+                               (ref->flags & RESOLVE_STATIC));
 
-       /* check protected access */
+               if (checkresult != resolveSucceeded)
+                       return (bool) checkresult;
 
-       if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
-       {
-               if (!resolve_and_check_subtype_set(referer,ref->referermethod,
-                                                                                  &(ref->instancetypes),
-                                                                                  CLASSREF_OR_CLASSINFO(referer),
-                                                                                  false,
-                                                                                  mode,
-                                                                                  resolveIllegalAccessError,&checked))
-               {
-                       return false; /* exception */
+               /* impose loading constraints on params and return type */
+
+               if (!resolve_method_loading_constraints(referer, mi))
+                       return false;
+
+               declarer = mi->class;
+               assert(declarer);
+               assert(referer->state & CLASS_LINKED);
+
+               /* for non-static methods we have to check the constraints on the         */
+               /* instance type                                                          */
+
+               if (!(ref->flags & RESOLVE_STATIC)) {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(container),
+                                       mode,
+                                       resolveLinkageError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
+                       instancecount = 1;
+               }
+               else {
+                       instancecount = 0;
                }
-               if (!checked)
-                       return true; /* be lazy */
-       }
 
-       /* impose loading constraints on parameters (including instance) */
+               /* check subtype constraints for TYPE_ADR parameters */
 
-       paramtypes = mi->parseddesc->paramtypes;
+               assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+               paramtypes = mi->parseddesc->paramtypes;
 
-       for (i = 0; i < mi->parseddesc->paramcount; i++) {
-               if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
-                       utf *name;
-                       
-                       if (i < instancecount) {
-                               /* The type of the 'this' pointer is the class containing */
-                               /* the method definition. Since container is the same as, */
-                               /* or a subclass of declarer, we also constrain declarer  */
-                               /* by transitivity of loading constraints.                */
-                               name = container->name;
-                       }
-                       else {
-                               name = paramtypes[i].classref->name;
+               for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
+                       if (paramtypes[i+instancecount].type == TYPE_ADR) {
+                               if (ref->paramconstraints) {
+                                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                                       ref->paramconstraints + i,
+                                                       CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
+                                                       mode,
+                                                       resolveLinkageError);
+                                       if (checkresult != resolveSucceeded)
+                                               return (bool) checkresult;
+                               }
                        }
-                       
-                       /* The caller (referer) and the callee (container) must agree */
-                       /* on the types of the parameters.                            */
-                       if (!classcache_add_constraint(referer->classloader,
-                                                                                  container->classloader, name))
-                               return false; /* exception */
                }
-       }
 
-       /* impose loading constraint onto return type */
+               /* check protected access */
 
-       if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
-               /* The caller (referer) and the callee (container) must agree */
-               /* on the return type.                                        */
-               if (!classcache_add_constraint(referer->classloader,container->classloader,
-                               ref->methodref->parseddesc.md->returntype.classref->name))
-                       return false; /* exception */
+               if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
+               {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(referer),
+                                       mode,
+                                       resolveIllegalAccessError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
+               }
        }
-
 #endif /* ENABLE_VERIFIER */
 
        /* succeed */
@@ -1327,42 +2266,42 @@ static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
                                                                                                 methodinfo *refmethod,
                                                                                                 unresolved_subtype_set *stset,
                                                                                                 typeinfo *tinfo,
-                                                                                                constant_classref *declaredtype)
+                                                                                                utf *declaredclassname)
 {
        int count;
        int i;
-       
+
        assert(stset);
        assert(tinfo);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
+       printf("unresolved_subtype_set_from_typeinfo\n");
 #ifdef TYPEINFO_DEBUG
-       typeinfo_print(stderr,tinfo,4);
+       typeinfo_print(stdout,tinfo,4);
 #endif
-       fprintf(stderr,"    declared type:");utf_fprint(stderr,declaredtype->name);
-       fprintf(stderr,"\n");
+       printf("    declared classname:");utf_fprint_printable_ascii(stdout,declaredclassname);
+       printf("\n");
 #endif
 
        if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
-               *exceptionptr = new_verifyerror(refmethod,
+               exceptions_throw_verifyerror(refmethod,
                                "Invalid use of returnAddress");
                return false;
        }
 
        if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
-               *exceptionptr = new_verifyerror(refmethod,
+               exceptions_throw_verifyerror(refmethod,
                                "Invalid use of uninitialized object");
                return false;
        }
 
-       /* the nulltype is always assignable (XXX for reversed?) */
+       /* the nulltype is always assignable */
        if (TYPEINFO_IS_NULLTYPE(*tinfo))
                goto empty_set;
 
        /* every type is assignable to (BOOTSTRAP)java.lang.Object */
-       if (declaredtype->name == utf_java_lang_Object
-                       && referer->classloader == NULL)
+       if (declaredclassname == utf_java_lang_Object
+                       && referer->classloader == NULL) /* XXX do loading constraints make the second check obsolete? */
        {
                goto empty_set;
        }
@@ -1389,8 +2328,8 @@ static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
        }
        else {
                if ((IS_CLASSREF(tinfo->typeclass)
-                                       ? tinfo->typeclass.ref->name 
-                                       : tinfo->typeclass.cls->name) == declaredtype->name)
+                                       ? tinfo->typeclass.ref->name
+                                       : tinfo->typeclass.cls->name) == declaredclassname)
                {
                        /* the class names are the same */
                    /* equality is guaranteed by the loading constraints */
@@ -1433,15 +2372,15 @@ unresolved_class * create_unresolved_class(methodinfo *refmethod,
                                                                                   typeinfo *valuetype)
 {
        unresolved_class *ref;
-       
+
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"create_unresolved_class\n");
-       fprintf(stderr,"    referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
+       printf("create_unresolved_class\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,classref->referer->name);fputc('\n',stdout);
        if (refmethod) {
-               fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
-               fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
+               printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+               printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
        }
-       fprintf(stderr,"    name   : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,classref->name);fputc('\n',stdout);
 #endif
 
        ref = NEW(unresolved_class);
@@ -1450,7 +2389,7 @@ unresolved_class * create_unresolved_class(methodinfo *refmethod,
 
        if (valuetype) {
                if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
-                                       &(ref->subtypeconstraints),valuetype,classref))
+                                       &(ref->subtypeconstraints),valuetype,classref->name))
                        return NULL;
        }
        else {
@@ -1461,7 +2400,7 @@ unresolved_class * create_unresolved_class(methodinfo *refmethod,
 }
 #endif /* ENABLE_VERIFIER */
 
-/* create_unresolved_field *****************************************************
+/* resolve_create_unresolved_field *********************************************
  
    Create an unresolved_field struct for the given field access instruction
   
@@ -1476,17 +2415,18 @@ unresolved_class * create_unresolved_class(methodinfo *refmethod,
 
 *******************************************************************************/
 
-unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refmethod,
-                                                                                  instruction *iptr)
+unresolved_field * resolve_create_unresolved_field(classinfo *referer,
+                                                                                                  methodinfo *refmethod,
+                                                                                                  instruction *iptr)
 {
        unresolved_field *ref;
        constant_FMIref *fieldref = NULL;
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"create_unresolved_field\n");
-       fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
+       printf("create_unresolved_field\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+       printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+       printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
 #endif
 
        ref = NEW(unresolved_field);
@@ -1494,46 +2434,46 @@ unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refme
        ref->referermethod = refmethod;
        UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
 
-       switch (iptr[0].opc) {
+       switch (iptr->opc) {
                case ICMD_PUTFIELD:
                        ref->flags |= RESOLVE_PUTFIELD;
-                       fieldref = (constant_FMIref *) iptr[0].val.a;
                        break;
 
                case ICMD_PUTFIELDCONST:
                        ref->flags |= RESOLVE_PUTFIELD;
-                       fieldref = (constant_FMIref *) iptr[1].val.a;
                        break;
 
                case ICMD_PUTSTATIC:
                        ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
-                       fieldref = (constant_FMIref *) iptr[0].val.a;
                        break;
 
                case ICMD_PUTSTATICCONST:
                        ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
-                       fieldref = (constant_FMIref *) iptr[1].val.a;
                        break;
 
                case ICMD_GETFIELD:
-                       fieldref = (constant_FMIref *) iptr[0].val.a;
                        break;
-                       
+
                case ICMD_GETSTATIC:
                        ref->flags |= RESOLVE_STATIC;
-                       fieldref = (constant_FMIref *) iptr[0].val.a;
                        break;
+
+#if !defined(NDEBUG)
+               default:
+                       assert(false);
+#endif
        }
-       
+
+       fieldref = iptr->sx.s23.s3.fmiref;
+
        assert(fieldref);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
-       fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
-       fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
-       fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
-       fputc('\n',stderr);
-       /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+/*     printf("    class  : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout);*/
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+       printf("    desc   : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
+       printf("    type   : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
+       fputc('\n',stdout);
 #endif
 
        ref->fieldref = fieldref;
@@ -1541,7 +2481,7 @@ unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refme
        return ref;
 }
 
-/* constrain_unresolved_field **************************************************
+/* resolve_constrain_unresolved_field ******************************************
  
    Record subtype constraints for a field access.
   
@@ -1549,8 +2489,8 @@ unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refme
        ref..............the unresolved_field structure of the access
        referer..........the class containing the reference
           refmethod........the method triggering the resolution (if any)
-          iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
-          stack............the input stack of the instruction
+          instanceti.......instance typeinfo, if available
+          valueti..........value typeinfo, if available
 
    RETURN VALUE:
        true.............everything ok
@@ -1558,17 +2498,16 @@ unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refme
 
 *******************************************************************************/
 
-#ifdef ENABLE_VERIFIER
-bool constrain_unresolved_field(unresolved_field *ref,
-                                                           classinfo *referer, methodinfo *refmethod,
-                                                           instruction *iptr,
-                                                           stackelement *stack)
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_field(unresolved_field *ref,
+                                                                               classinfo *referer, 
+                                                                               methodinfo *refmethod,
+                                                                           typeinfo *instanceti,
+                                                                           typeinfo *valueti)
 {
        constant_FMIref *fieldref;
-       stackelement *instanceslot = NULL;
        int type;
        typeinfo tinfo;
-       typeinfo *tip = NULL;
        typedesc *fd;
 
        assert(ref);
@@ -1577,67 +2516,50 @@ bool constrain_unresolved_field(unresolved_field *ref,
        assert(fieldref);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"constrain_unresolved_field\n");
-       fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
-       fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
-       fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
-       fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
-       fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
-       fputc('\n',stderr);
-       /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+       printf("constrain_unresolved_field\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+       printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+       printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+/*     printf("    class  : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout); */
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+       printf("    desc   : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
+       printf("    type   : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
+       fputc('\n',stdout);
 #endif
 
-       switch (iptr[0].opc) {
-               case ICMD_PUTFIELD:
-                       instanceslot = stack->prev;
-                       tip = &(stack->typeinfo);
-                       break;
-
-               case ICMD_PUTFIELDCONST:
-                       instanceslot = stack;
-                       break;
-
-               case ICMD_PUTSTATIC:
-                       tip = &(stack->typeinfo);
-                       break;
-
-               case ICMD_GETFIELD:
-                       instanceslot = stack;
-                       break;
-       }
-       
-       assert(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
+       assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
        fd = fieldref->parseddesc.fd;
        assert(fd);
 
        /* record subtype constraints for the instance type, if any */
-       if (instanceslot) {
+       if (instanceti) {
                typeinfo *insttip;
 
                /* The instanceslot must contain a reference to a non-array type */
-               if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
-                       *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on non-reference");
+               if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, 
+                                       "illegal instruction: field access on non-reference");
                        return false;
                }
-               if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
-                       *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
+               if (TYPEINFO_IS_ARRAY(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, 
+                                       "illegal instruction: field access on array");
                        return false;
                }
-               
-               if (((ref->flags & RESOLVE_PUTFIELD) != 0) && 
-                               TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
+
+               if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
+                               TYPEINFO_IS_NEWOBJECT(*instanceti))
                {
                        /* The instruction writes a field in an uninitialized object. */
                        /* This is only allowed when a field of an uninitialized 'this' object is */
                        /* written inside an initialization method                                */
-                       
+
                        classinfo *initclass;
-                       instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
+                       instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
 
                        if (ins != NULL) {
-                               *exceptionptr = new_verifyerror(refmethod,"accessing field of uninitialized object");
+                               exceptions_throw_verifyerror(refmethod, 
+                                               "accessing field of uninitialized object");
                                return false;
                        }
                        /* XXX check that class of field == refmethod->class */
@@ -1645,37 +2567,28 @@ bool constrain_unresolved_field(unresolved_field *ref,
                        assert(initclass->state & CLASS_LOADED);
                        assert(initclass->state & CLASS_LINKED);
 
-                       typeinfo_init_classinfo(&tinfo,initclass);
+                       typeinfo_init_classinfo(&tinfo, initclass);
                        insttip = &tinfo;
                }
                else {
-                       insttip = &(instanceslot->typeinfo);
+                       insttip = instanceti;
                }
-               if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
-                                       &(ref->instancetypes),insttip,fieldref->classref))
+               if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+                                       &(ref->instancetypes), insttip, 
+                                       FIELDREF_CLASSNAME(fieldref)))
                        return false;
        }
        else {
                UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
        }
-       
+
        /* record subtype constraints for the value type, if any */
        type = fd->type;
        if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
-               if (!tip) {
-                       /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
-                       tip = &tinfo;
-                       if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
-                               assert(class_java_lang_String);
-                               assert(class_java_lang_String->state & CLASS_LOADED);
-                               assert(class_java_lang_String->state & CLASS_LINKED);
-                               typeinfo_init_classinfo(&tinfo,class_java_lang_String);
-                       }
-                       else
-                               TYPEINFO_INIT_NULLTYPE(tinfo);
-               }
-               if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
-                                       &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
+               assert(valueti);
+               if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+                                       &(ref->valueconstraints), valueti, 
+                                       fieldref->parseddesc.fd->classref->name))
                        return false;
        }
        else {
@@ -1686,7 +2599,7 @@ bool constrain_unresolved_field(unresolved_field *ref,
 }
 #endif /* ENABLE_VERIFIER */
 
-/* create_unresolved_method ****************************************************
+/* resolve_create_unresolved_method ********************************************
  
    Create an unresolved_method struct for the given method invocation
   
@@ -1701,38 +2614,35 @@ bool constrain_unresolved_field(unresolved_field *ref,
 
 *******************************************************************************/
 
-unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *refmethod,
-                                                                                        instruction *iptr)
+unresolved_method * resolve_create_unresolved_method(classinfo *referer,
+                                                                                                        methodinfo *refmethod,
+                                                                                                        constant_FMIref *methodref,
+                                                                                                        bool invokestatic,
+                                                                                                        bool invokespecial)
 {
        unresolved_method *ref;
-       constant_FMIref *methodref;
-       bool staticmethod;
 
-       methodref = (constant_FMIref *) iptr[0].val.a;
        assert(methodref);
-       staticmethod = (iptr[0].opc == ICMD_INVOKESTATIC);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"create_unresolved_method\n");
-       fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
-       fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
-       fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
-       fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
-       /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+       printf("create_unresolved_method\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+       printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+       printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,methodref->name);fputc('\n',stdout);
+       printf("    desc   : ");utf_fprint_printable_ascii(stdout,methodref->descriptor);fputc('\n',stdout);
 #endif
 
        /* allocate params if necessary */
        if (!methodref->parseddesc.md->params)
                if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
-                                       (staticmethod) ? ACC_STATIC : ACC_NONE))
+                                       (invokestatic) ? ACC_STATIC : ACC_NONE))
                        return NULL;
 
        /* create the data structure */
        ref = NEW(unresolved_method);
-       ref->flags = ((staticmethod) ? RESOLVE_STATIC : 0)
-                          | ((iptr[0].opc == ICMD_INVOKESPECIAL) ? RESOLVE_SPECIAL : 0);
+       ref->flags = ((invokestatic) ? RESOLVE_STATIC : 0)
+                          | ((invokespecial) ? RESOLVE_SPECIAL : 0);
        ref->referermethod = refmethod;
        ref->methodref = methodref;
        ref->paramconstraints = NULL;
@@ -1741,16 +2651,16 @@ unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *ref
        return ref;
 }
 
-/* constrain_unresolved_method *************************************************
+
+/* resolve_constrain_unresolved_method_instance ********************************
  
-   Record subtype constraints for the arguments of a method call.
+   Record subtype constraints for the instance argument of a method call.
   
    IN:
        ref..............the unresolved_method structure of the call
        referer..........the class containing the reference
           refmethod........the method triggering the resolution (if any)
           iptr.............the INVOKE* instruction
-          stack............the input stack of the instruction
 
    RETURN VALUE:
        true.............everything ok
@@ -1758,17 +2668,81 @@ unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *ref
 
 *******************************************************************************/
 
-#ifdef ENABLE_VERIFIER
-bool constrain_unresolved_method(unresolved_method *ref,
-                                                                classinfo *referer, methodinfo *refmethod,
-                                                                instruction *iptr,
-                                                                stackelement *stack)
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
+                                                                                                 methodinfo *refmethod,
+                                                                                                 typeinfo *instanceti,
+                                                                                                 bool invokespecial)
+{
+       constant_FMIref   *methodref;
+       constant_classref *instanceref;
+       typeinfo           tinfo;
+       typeinfo          *tip;
+
+       assert(ref);
+       methodref = ref->methodref;
+       assert(methodref);
+
+       /* XXX clean this up */
+       instanceref = IS_FMIREF_RESOLVED(methodref)
+               ? class_get_self_classref(methodref->p.method->class)
+               : methodref->p.classref;
+
+#ifdef RESOLVE_VERBOSE
+       printf("resolve_constrain_unresolved_method_instance\n");
+       printf("    rmethod: "); method_println(refmethod);
+       printf("    mref   : "); method_methodref_println(methodref);
+#endif
+
+       /* record subtype constraints for the instance type, if any */
+
+       if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
+       {   /* XXX clean up */
+               instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+               classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
+                                                                        : CLASSREF_OR_CLASSINFO(refmethod->class);
+               tip = &tinfo;
+               if (!typeinfo_init_class(tip, initclass))
+                       return false;
+       }
+       else {
+               tip = instanceti;
+       }
+
+       if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+                               &(ref->instancetypes),tip,instanceref->name))
+               return false;
+
+       return true;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_constrain_unresolved_method_params  *********************************
+   Record subtype constraints for the non-instance arguments of a method call.
+  
+   IN:
+       jd...............current jitdata (for looking up variables)
+       ref..............the unresolved_method structure of the call
+          refmethod........the method triggering the resolution (if any)
+          iptr.............the INVOKE* instruction
+
+   RETURN VALUE:
+       true.............everything ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_params(jitdata *jd,
+                                                                                               unresolved_method *ref,
+                                                                                               methodinfo *refmethod,
+                                                                                               instruction *iptr)
 {
        constant_FMIref *methodref;
-       stackelement *instanceslot = NULL;
-       stackelement *param;
+       varinfo *param;
        methoddesc *md;
-       typeinfo tinfo;
        int i,j;
        int type;
        int instancecount;
@@ -1781,83 +2755,122 @@ bool constrain_unresolved_method(unresolved_method *ref,
        assert(md->params != NULL);
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"constrain_unresolved_method\n");
-       fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
-       fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
-       fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
-       fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
-       fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
-       /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+       printf("resolve_constrain_unresolved_method_params\n");
+       printf("    rmethod: "); method_println(refmethod);
+       printf("    mref   : "); method_methodref_println(methodref);
 #endif
 
-       if ((ref->flags & RESOLVE_STATIC) == 0) {
-               /* find the instance slot under all the parameter slots on the stack */
-               instanceslot = stack;
-               for (i=1; i<md->paramcount; ++i)
-                       instanceslot = instanceslot->prev;
-               instancecount = 1;
-       }
-       else {
-               instancecount = 0;
-       }
-       
-       assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
+       instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
 
-       /* record subtype constraints for the instance type, if any */
-       if (instanceslot) {
-               typeinfo *tip;
-               
-               assert(instanceslot->type == TYPE_ADR);
-               
-               if (iptr[0].opc == ICMD_INVOKESPECIAL && 
-                               TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
-               {   /* XXX clean up */
-                       instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
-                       classref_or_classinfo initclass = (ins) ? CLASSREF_OR_CLASSINFO(ins[-1].target)
-                                                                                : CLASSREF_OR_CLASSINFO(refmethod->class);
-                       tip = &tinfo;
-                       if (!typeinfo_init_class(tip,initclass))
+       /* record subtype constraints for the parameter types, if any */
+
+       for (i=md->paramcount-1-instancecount; i>=0; --i) {
+               param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+               type = md->paramtypes[i+instancecount].type;
+
+               assert(param);
+               assert(type == param->type);
+
+               if (type == TYPE_ADR) {
+                       if (!ref->paramconstraints) {
+                               ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
+                               for (j=md->paramcount-1-instancecount; j>i; --j)
+                                       UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
+                       }
+                       assert(ref->paramconstraints);
+                       if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+                                               ref->paramconstraints + i,&(param->typeinfo),
+                                               md->paramtypes[i+instancecount].classref->name))
                                return false;
                }
                else {
-                       tip = &(instanceslot->typeinfo);
+                       if (ref->paramconstraints)
+                               UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
                }
-               if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
-                                       &(ref->instancetypes),tip,methodref->classref))
-                       return false;
        }
-       
+
+       return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/* resolve_constrain_unresolved_method_params_stackbased ***********************
+   Record subtype constraints for the non-instance arguments of a method call.
+  
+   IN:
+       ref..............the unresolved_method structure of the call
+          refmethod........the method triggering the resolution (if any)
+          stack............TOS before the INVOKE instruction
+
+   RETURN VALUE:
+       true.............everything ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_params_stackbased(
+               unresolved_method *ref,
+               methodinfo *refmethod,
+               typedescriptor *stack)
+{
+       constant_FMIref *methodref;
+       typedescriptor *param;
+       methoddesc *md;
+       int i,j;
+       int type;
+       int instancecount;
+
+       assert(ref);
+       methodref = ref->methodref;
+       assert(methodref);
+       md = methodref->parseddesc.md;
+       assert(md);
+       assert(md->params != NULL);
+
+#ifdef RESOLVE_VERBOSE
+       printf("resolve_constrain_unresolved_method_params_stackbased\n");
+       printf("    rmethod: "); method_println(refmethod);
+       printf("    mref   : "); method_methodref_println(methodref);
+#endif
+
+       instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
+
        /* record subtype constraints for the parameter types, if any */
-       param = stack;
-       for (i=md->paramcount-1-instancecount; i>=0; --i, param=param->prev) {
-               type = md->paramtypes[i+instancecount].type;
 
-               assert(param);
+       param = stack - (md->paramslots - 1 - instancecount);
+
+       for (i = instancecount; i < md->paramcount; ++i) {
+               type = md->paramtypes[i].type;
+
                assert(type == param->type);
 
                if (type == TYPE_ADR) {
                        if (!ref->paramconstraints) {
                                ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
-                               for (j=md->paramcount-1-instancecount; j>i; --j)
+                               for (j = 0; j < i - instancecount; ++j)
                                        UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
                        }
                        assert(ref->paramconstraints);
-                       if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
-                                               ref->paramconstraints + i,&(param->typeinfo),
-                                               md->paramtypes[i+instancecount].classref))
+                       if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+                                               ref->paramconstraints + i - instancecount,&(param->typeinfo),
+                                               md->paramtypes[i].classref->name))
                                return false;
                }
                else {
                        if (ref->paramconstraints)
                                UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
                }
+
+               param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
        }
 
        return true;
 }
 #endif /* ENABLE_VERIFIER */
 
+
 /******************************************************************************/
 /* FREEING MEMORY                                                             */
 /******************************************************************************/
@@ -1942,11 +2955,12 @@ void unresolved_method_free(unresolved_method *ref)
        FREE(ref,unresolved_method);
 }
 
-#ifndef NDEBUG
 /******************************************************************************/
 /* DEBUG DUMPS                                                                */
 /******************************************************************************/
 
+#if !defined(NDEBUG)
+
 /* unresolved_subtype_set_debug_dump *******************************************
  
    Print debug info for unresolved_subtype_set to stream
@@ -1960,7 +2974,7 @@ void unresolved_method_free(unresolved_method *ref)
 void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
 {
        classref_or_classinfo *p;
-       
+
        if (SUBTYPESET_IS_EMPTY(*stset)) {
                fprintf(file,"        (empty)\n");
        }
@@ -1969,11 +2983,11 @@ void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
                for (;p->any; ++p) {
                        if (IS_CLASSREF(*p)) {
                                fprintf(file,"        ref: ");
-                               utf_fprint(file,p->ref->name);
+                               utf_fprint_printable_ascii(file,p->ref->name);
                        }
                        else {
                                fprintf(file,"        cls: ");
-                               utf_fprint(file,p->cls->name);
+                               utf_fprint_printable_ascii(file,p->cls->name);
                        }
                        fputc('\n',file);
                }
@@ -1995,13 +3009,13 @@ void unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
        fprintf(file,"unresolved_class(%p):\n",(void *)ref);
        if (ref) {
                fprintf(file,"    referer   : ");
-               utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->classref->referer->name); fputc('\n',file);
                fprintf(file,"    refmethod : ");
-               utf_fprint(file,ref->referermethod->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
                fprintf(file,"    refmethodd: ");
-               utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
                fprintf(file,"    classname : ");
-               utf_fprint(file,ref->classref->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->classref->name); fputc('\n',file);
                fprintf(file,"    subtypeconstraints:\n");
                unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
        }
@@ -2022,17 +3036,17 @@ void unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
        fprintf(file,"unresolved_field(%p):\n",(void *)ref);
        if (ref) {
                fprintf(file,"    referer   : ");
-               utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
                fprintf(file,"    refmethod : ");
-               utf_fprint(file,ref->referermethod->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
                fprintf(file,"    refmethodd: ");
-               utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
                fprintf(file,"    classname : ");
-               utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,FIELDREF_CLASSNAME(ref->fieldref)); fputc('\n',file);
                fprintf(file,"    name      : ");
-               utf_fprint(file,ref->fieldref->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->fieldref->name); fputc('\n',file);
                fprintf(file,"    descriptor: ");
-               utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->fieldref->descriptor); fputc('\n',file);
                fprintf(file,"    parseddesc: ");
                descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
                fprintf(file,"    flags     : %04x\n",ref->flags);
@@ -2060,17 +3074,17 @@ void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
        fprintf(file,"unresolved_method(%p):\n",(void *)ref);
        if (ref) {
                fprintf(file,"    referer   : ");
-               utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
                fprintf(file,"    refmethod : ");
-               utf_fprint(file,ref->referermethod->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
                fprintf(file,"    refmethodd: ");
-               utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
                fprintf(file,"    classname : ");
-               utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,METHODREF_CLASSNAME(ref->methodref)); fputc('\n',file);
                fprintf(file,"    name      : ");
-               utf_fprint(file,ref->methodref->name); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->methodref->name); fputc('\n',file);
                fprintf(file,"    descriptor: ");
-               utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
+               utf_fprint_printable_ascii(file,ref->methodref->descriptor); fputc('\n',file);
                fprintf(file,"    parseddesc: ");
                descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
                fprintf(file,"    flags     : %04x\n",ref->flags);
@@ -2082,13 +3096,14 @@ void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
                                fprintf(file,"      param %d:\n",i);
                                unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
                        }
-               } 
+               }
                else {
                        fprintf(file,"      (empty)\n");
                }
        }
 }
-#endif
+#endif /* !defined(NDEBUG) */
+
 
 /*
  * These are local overrides for various environment variables in Emacs.
@@ -2103,4 +3118,3 @@ void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
  * End:
  * vim:noexpandtab:sw=4:ts=4:
  */
-