* renamed CACAO_TYPECHECK to ENABLE_VERIFIER
[cacao.git] / src / vm / resolve.c
index 0f30a3d825eff7685356ee5feb75f93ef3d76f90..f8de23e5f231eb811b4c5b9c9cd6a895c5549c9f 100644 (file)
@@ -26,9 +26,9 @@
 
    Authors: Edwin Steiner
 
-   Changes:
+   Changes: Christan Thalinger
 
-   $Id: resolve.c 2195 2005-04-03 16:53:16Z edwin $
+   $Id: resolve.c 3811 2005-11-28 16:23:40Z edwin $
 
 */
 
 #include "vm/resolve.h"
 #include "vm/access.h"
 #include "vm/classcache.h"
+#include "vm/descriptor.h"
 #include "vm/exceptions.h"
-#include "vm/loader.h"
 #include "vm/linker.h"
-#include "vm/classcache.h"
-#include "vm/descriptor.h"
+#include "vm/loader.h"
+#include "vm/stringlocal.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/verify/typeinfo.h"
 
 
 /*#define RESOLVE_VERBOSE*/
 
-#ifndef NDEBUG
-#define RESOLVE_DEBUG
-#endif
-
-#ifdef RESOLVE_DEBUG
-#define RESOLVE_ASSERT(cond)  assert(cond)
-#else
-#define RESOLVE_ASSERT(cond)
-#endif
-
 /******************************************************************************/
 /* CLASS RESOLUTION                                                           */
 /******************************************************************************/
 
-/* resolve symbolic class reference -- see resolve.h */
-bool
-resolve_class(classinfo *referer,methodinfo *refmethod,
-                         utf *classname,
-                         resolve_mode_t mode,
-                         classinfo **result)
+/* resolve_class_from_name *****************************************************
+   Resolve a symbolic class reference
+  
+   IN:
+       referer..........the class containing the reference
+       refmethod........the method from which resolution was triggered
+                        (may be NULL if not applicable)
+       classname........class name to resolve
+       mode.............mode of resolution:
+                            resolveLazy...only resolve if it does not
+                                          require loading classes
+                            resolveEager..load classes if necessary
+          checkaccess......if true, access rights to the class are checked
+          link.............if true, guarantee that the returned class, if any,
+                           has been linked
+  
+   OUT:
+       *result..........set to 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
+
+   NOTE:
+       The returned class is *not* guaranteed to be linked!
+          (It is guaranteed to be loaded, though.)
+   
+*******************************************************************************/
+
+bool resolve_class_from_name(classinfo *referer,
+                                                        methodinfo *refmethod,
+                                                        utf *classname,
+                                                        resolve_mode_t mode,
+                                                        bool checkaccess,
+                                                        bool link,
+                                                        classinfo **result)
 {
        classinfo *cls = NULL;
        char *utf_ptr;
        int len;
        
-       RESOLVE_ASSERT(result);
-       RESOLVE_ASSERT(referer);
-       RESOLVE_ASSERT(classname);
-       RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
+       assert(result);
+       assert(referer);
+       assert(classname);
+       assert(mode == resolveLazy || mode == resolveEager);
        
        *result = NULL;
 
 #ifdef RESOLVE_VERBOSE
-       fprintf(stderr,"resolve_class(");
+       fprintf(stderr,"resolve_class_from_name(");
        utf_fprint(stderr,referer->name);
-       fprintf(stderr,",");
+       fprintf(stderr,",%p,",referer->classloader);
        utf_fprint(stderr,classname);
-       fprintf(stderr,")\n");
+       fprintf(stderr,",%d,%d)\n",(int)checkaccess,(int)link);
 #endif
 
        /* lookup if this class has already been loaded */
-       cls = classcache_lookup(referer->classloader,classname);
+
+       cls = classcache_lookup(referer->classloader, classname);
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    lookup result: %p\n",(void*)cls);
 #endif
-       
+
        if (!cls) {
                /* resolve array types */
+
                if (classname->text[0] == '[') {
                        utf_ptr = classname->text + 1;
                        len = classname->blength - 1;
+
                        /* classname is an array type name */
+
                        switch (*utf_ptr) {
                                case 'L':
                                        utf_ptr++;
@@ -115,12 +144,12 @@ resolve_class(classinfo *referer,methodinfo *refmethod,
                                case '[':
                                        /* the component type is a reference type */
                                        /* resolve the component type */
-                                       if (!resolve_class(referer,refmethod,
+                                       if (!resolve_class_from_name(referer,refmethod,
                                                                           utf_new(utf_ptr,len),
-                                                                          mode,&cls))
+                                                                          mode,checkaccess,link,&cls))
                                                return false; /* exception */
                                        if (!cls) {
-                                               RESOLVE_ASSERT(mode == resolveLazy);
+                                               assert(mode == resolveLazy);
                                                return true; /* be lazy */
                                        }
                                        /* create the array class */
@@ -141,26 +170,45 @@ resolve_class(classinfo *referer,methodinfo *refmethod,
 
                /* load the class */
                if (!cls) {
-                       if (!load_class_from_classloader(classname,referer->classloader,&cls))
+                       if (!(cls = load_class_from_classloader(classname,
+                                                                                                       referer->classloader)))
                                return false; /* exception */
                }
        }
 
        /* the class is now loaded */
-       RESOLVE_ASSERT(cls);
-       RESOLVE_ASSERT(cls->loaded);
+       assert(cls);
+       assert(cls->loaded);
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    checking access rights...\n");
 #endif
        
        /* check access rights of referer to refered class */
-       if (!is_accessible_class(referer,cls)) {
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
-                               "class is not accessible XXX add message");
+       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);
                return false; /* exception */
        }
 
+       /* link the class if necessary */
+       if (link) {
+               if (!cls->linked)
+                       if (!link_class(cls))
+                               return false; /* exception */
+               assert(cls->linked);
+       }
+
        /* resolution succeeds */
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    success.\n");
@@ -169,101 +217,189 @@ resolve_class(classinfo *referer,methodinfo *refmethod,
        return true;
 }
 
-bool
-resolve_classref(methodinfo *refmethod,
-                                constant_classref *ref,
-                                resolve_mode_t mode,
-                            bool link,
-                                classinfo **result)
+/* resolve_classref ************************************************************
+   Resolve a symbolic class reference
+  
+   IN:
+       refmethod........the method from which resolution was triggered
+                        (may be NULL if not applicable)
+       ref..............class reference
+       mode.............mode of resolution:
+                            resolveLazy...only resolve if it does not
+                                          require loading classes
+                            resolveEager..load classes if necessary
+          checkaccess......if true, access rights to the class are checked
+          link.............if true, guarantee that the returned class, if any,
+                           has been linked
+  
+   OUT:
+       *result..........set to 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_classref(methodinfo *refmethod,
+                                         constant_classref *ref,
+                                         resolve_mode_t mode,
+                                         bool checkaccess,
+                                         bool link,
+                                         classinfo **result)
 {
-       return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
+       return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,checkaccess,link,result);
 }
 
-bool
-resolve_classref_or_classinfo(methodinfo *refmethod,
-                                                         classref_or_classinfo cls,
-                                                         resolve_mode_t mode,
-                                                         bool link,
-                                                         classinfo **result)
+/* resolve_classref_or_classinfo ***********************************************
+   Resolve a symbolic class reference if necessary
+  
+   IN:
+       refmethod........the method from which resolution was triggered
+                        (may be NULL if not applicable)
+       cls..............class reference or classinfo
+       mode.............mode of resolution:
+                            resolveLazy...only resolve if it does not
+                                          require loading classes
+                            resolveEager..load classes if necessary
+          checkaccess......if true, access rights to the class are checked
+          link.............if true, guarantee that the returned class, if any,
+                           has been linked
+  
+   OUT:
+       *result..........set to 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_classref_or_classinfo(methodinfo *refmethod,
+                                                                  classref_or_classinfo cls,
+                                                                  resolve_mode_t mode,
+                                                                  bool checkaccess,
+                                                                  bool link,
+                                                                  classinfo **result)
 {
-       classinfo *c;
+       classinfo         *c;
        
-       RESOLVE_ASSERT(cls.any);
-       RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
-       RESOLVE_ASSERT(result);
+       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)\n",mode,link);
+       fprintf(stderr,",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
 #endif
 
        *result = NULL;
 
        if (IS_CLASSREF(cls)) {
                /* we must resolve this reference */
-               if (!resolve_class(cls.ref->referer,refmethod,cls.ref->name,
-                                                  mode,&c))
-                       return false; /* exception */
-       }
-       else {
+
+               if (!resolve_class_from_name(cls.ref->referer, refmethod, cls.ref->name,
+                                                                        mode, checkaccess, link, &c))
+                       goto return_exception;
+
+       } else {
                /* cls has already been resolved */
                c = cls.cls;
-               RESOLVE_ASSERT(c->loaded);
+               assert(c->loaded);
        }
-       RESOLVE_ASSERT(c || (mode == resolveLazy));
+       assert(c || (mode == resolveLazy));
 
        if (!c)
                return true; /* be lazy */
        
-       RESOLVE_ASSERT(c);
-       RESOLVE_ASSERT(c->loaded);
+       assert(c);
+       assert(c->loaded);
 
        if (link) {
                if (!c->linked)
                        if (!link_class(c))
-                               return false; /* exception */
-               RESOLVE_ASSERT(c->linked);
+                               goto return_exception;
+
+               assert(c->linked);
        }
 
        /* succeeded */
        *result = c;
        return true;
+
+ return_exception:
+       *result = NULL;
+       return false;
 }
 
-bool 
-resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
+
+/* resolve_class_from_typedesc *************************************************
+   Return a classinfo * for the given type descriptor
+  
+   IN:
+       d................type descriptor
+          checkaccess......if true, access rights to the class are checked
+          link.............if true, guarantee that the returned class, if any,
+                           has been linked
+   OUT:
+       *result..........set to 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 
+       false............an exception has been thrown
+
+   NOTE:
+       This function always resolved eagerly.
+   
+*******************************************************************************/
+
+bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
 {
        classinfo *cls;
        
-       RESOLVE_ASSERT(d);
-       RESOLVE_ASSERT(result);
+       assert(d);
+       assert(result);
 
        *result = NULL;
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"resolve_class_from_typedesc(");
        descriptor_debug_print_typedesc(stderr,d);
-       fprintf(stderr,",%i)\n",link);
+       fprintf(stderr,",%i,%i)\n",(int)checkaccess,(int)link);
 #endif
 
        if (d->classref) {
                /* a reference type */
                if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
-                                                                                  resolveEager,link,&cls))
+                                                                                  resolveEager,checkaccess,link,&cls))
                        return false; /* exception */
        }
        else {
                /* a primitive type */
                cls = primitivetype_table[d->decltype].class_primitive;
-               RESOLVE_ASSERT(cls->loaded);
+               assert(cls->loaded);
                if (!cls->linked)
                        if (!link_class(cls))
                                return false; /* exception */
        }
-       RESOLVE_ASSERT(cls);
-       RESOLVE_ASSERT(cls->loaded);
-       RESOLVE_ASSERT(!link || cls->linked);
+       assert(cls);
+       assert(cls->loaded);
+       assert(!link || cls->linked);
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
@@ -277,27 +413,73 @@ resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
 /* SUBTYPE SET CHECKS                                                         */
 /******************************************************************************/
 
-/* for documentation see resolve.h */
-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)
+#ifdef 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
+       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.
+
+   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.
+   
+   NOTE:
+       The references in the set are resolved first, so any
+       exception which may occurr during resolution may
+       be thrown by this function.
+   
+*******************************************************************************/
+
+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)
 {
        classref_or_classinfo *setp;
        classinfo *result;
        classinfo *type;
        typeinfo resultti;
        typeinfo typeti;
+       char *message;
+       int msglen;
+       typecheck_result r;
 
-       RESOLVE_ASSERT(referer);
-       RESOLVE_ASSERT(ref);
-       RESOLVE_ASSERT(typeref.any);
-       RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
-       RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
+       assert(referer);
+       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");
@@ -324,26 +506,37 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
                *checked = false;
 
        /* first resolve the type if necessary */
-       if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
+       if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&type))
                return false; /* exception */
        if (!type)
                return true; /* be lazy */
 
-       RESOLVE_ASSERT(type);
-       RESOLVE_ASSERT(type->loaded);
-       RESOLVE_ASSERT(type->linked);
-       TYPEINFO_INIT_CLASSINFO(typeti,type);
+       assert(type);
+       assert(type->loaded);
+       assert(type->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,true,&result))
-                       return false; /* exception */
+               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 */
 
-               RESOLVE_ASSERT(result);
-               RESOLVE_ASSERT(result->loaded);
-               RESOLVE_ASSERT(result->linked);
+               assert(result);
+               assert(result->loaded);
+               assert(result->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");
@@ -353,10 +546,13 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
 #endif
 
                /* now check the subtype relationship */
-               TYPEINFO_INIT_CLASSINFO(resultti,result);
+               typeinfo_init_classinfo(&resultti,result);
                if (reversed) {
                        /* we must test against `true` because `MAYBE` is also != 0 */
-                       if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
+                       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
@@ -365,7 +561,10 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
                }
                else {
                        /* we must test against `true` because `MAYBE` is also != 0 */
-                       if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
+                       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");
 #endif
@@ -380,24 +579,218 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
        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,
-                               "illegal access to protected member XXX add message");
+               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
        else
-               *exceptionptr = new_exception_message(string_java_lang_LinkageError,
-                               "subtype constraint violated XXX add message");
+               *exceptionptr = exceptions_new_linkageerror(message,NULL);
+       MFREE(message,char,msglen);
        return false; /* exception */
 }
 
+#endif /* ENABLE_VERIFIER */
+
+/******************************************************************************/
+/* CLASS RESOLUTION                                                           */
+/******************************************************************************/
+
+/* resolve_class ***************************************************************
+   Resolve an unresolved class reference. The class is also linked.
+  
+   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
+          checkaccess......if true, access rights to the class are checked
+   
+   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
+   
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool resolve_class(unresolved_class *ref,
+                                  resolve_mode_t mode,
+                                  bool checkaccess,
+                                  classinfo **result)
+{
+       classinfo *cls;
+       bool checked;
+       
+       assert(ref);
+       assert(result);
+       assert(mode == resolveLazy || mode == resolveEager);
+
+       *result = NULL;
+
+#ifdef RESOLVE_VERBOSE
+       unresolved_class_debug_dump(ref,stderr);
+#endif
+
+       /* first we must resolve the class */
+       if (!resolve_classref(ref->referermethod,
+                                             ref->classref,mode,checkaccess,true,&cls))
+       {
+               /* the class reference could not be resolved */
+               return false; /* exception */
+       }
+       if (!cls)
+               return true; /* be lazy */
+
+       assert(cls);
+       assert(cls->loaded && cls->linked);
+
+       /* now we check the subtype constraints */
+       if (!resolve_and_check_subtype_set(ref->classref->referer,ref->referermethod,
+                                                                          &(ref->subtypeconstraints),
+                                                                          CLASSREF_OR_CLASSINFO(cls),
+                                                                          false,
+                                                                          mode,
+                                                                          resolveLinkageError,&checked))
+       {
+               return false; /* exception */
+       }
+       if (!checked)
+               return true; /* be lazy */
+
+       /* succeed */
+       *result = cls;
+       return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* resolve_classref_eager ******************************************************
+   Resolve an unresolved class reference eagerly. The class is also linked and
+   access rights to the class are checked.
+  
+   IN:
+       ref..............constant_classref to the class
+   
+   RETURN VALUE:
+       classinfo * to the class, or
+          NULL if an exception has been thrown
+   
+*******************************************************************************/
+
+classinfo * resolve_classref_eager(constant_classref *ref)
+{
+       classinfo *c;
+
+       if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
+               return NULL;
+
+       return c;
+}
+
+/* resolve_classref_eager_nonabstract ******************************************
+   Resolve an unresolved class reference eagerly. The class is also linked and
+   access rights to the class are checked. A check is performed that the class
+   is not abstract.
+  
+   IN:
+       ref..............constant_classref to the class
+   
+   RETURN VALUE:
+       classinfo * to the class, or
+          NULL if an exception has been thrown
+   
+*******************************************************************************/
+
+classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
+{
+       classinfo *c;
+
+       if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
+               return NULL;
+
+       /* ensure that the class is not abstract */
+
+       if (c->flags & ACC_ABSTRACT) {
+               *exceptionptr = new_verifyerror(NULL,"creating instance of abstract class");
+               return NULL;
+       }
+
+       return c;
+}
+
+/* resolve_class_eager *********************************************************
+   Resolve an unresolved class reference eagerly. The class is also linked and
+   access rights to the class are checked.
+  
+   IN:
+       ref..............struct containing the reference
+   
+   RETURN VALUE:
+       classinfo * to the class, or
+          NULL if an exception has been thrown
+   
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+classinfo * resolve_class_eager(unresolved_class *ref)
+{
+       classinfo *c;
+
+       if (!resolve_class(ref,resolveEager,true,&c))
+               return NULL;
+
+       return c;
+}
+#endif /* ENABLE_VERIFIER */
+
 /******************************************************************************/
 /* FIELD RESOLUTION                                                           */
 /******************************************************************************/
 
-/* for documentation see resolve.h */
-bool
-resolve_field(unresolved_field *ref,
-                         resolve_mode_t mode,
-                         fieldinfo **result)
+/* 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;
@@ -406,9 +799,9 @@ resolve_field(unresolved_field *ref,
        fieldinfo *fi;
        bool checked;
        
-       RESOLVE_ASSERT(ref);
-       RESOLVE_ASSERT(result);
-       RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
+       assert(ref);
+       assert(result);
+       assert(mode == resolveLazy || mode == resolveEager);
 
        *result = NULL;
 
@@ -417,12 +810,13 @@ resolve_field(unresolved_field *ref,
 #endif
 
        /* the class containing the reference */
+
        referer = ref->fieldref->classref->referer;
-       RESOLVE_ASSERT(referer);
+       assert(referer);
 
        /* first we must resolve the class containg the field */
-       if (!resolve_class(referer,ref->referermethod,
-                                          ref->fieldref->classref->name,mode,&container))
+       if (!resolve_class_from_name(referer,ref->referermethod,
+                                          ref->fieldref->classref->name,mode,true,true,&container))
        {
                /* the class reference could not be resolved */
                return false; /* exception */
@@ -430,8 +824,8 @@ resolve_field(unresolved_field *ref,
        if (!container)
                return true; /* be lazy */
 
-       RESOLVE_ASSERT(container);
-       RESOLVE_ASSERT(container->loaded && container->linked);
+       assert(container);
+       assert(container->loaded && container->linked);
 
        /* now we must find the declaration of the field in `container`
         * or one of its superclasses */
@@ -443,19 +837,32 @@ resolve_field(unresolved_field *ref,
        fi = class_resolvefield(container,
                                                        ref->fieldref->name,ref->fieldref->descriptor,
                                                        referer,true);
-       if (!fi)
+       if (!fi) {
+               if (mode == resolveLazy) {
+                       /* 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.)           */
+
+                       *exceptionptr = NULL;
+                       return true; /* be lazy */
+               }
+               
                return false; /* exception */
+       }
+
+#ifdef ENABLE_VERIFIER
 
        /* { the field reference has been resolved } */
        declarer = fi->class;
-       RESOLVE_ASSERT(declarer);
-       RESOLVE_ASSERT(declarer->loaded && declarer->linked);
+       assert(declarer);
+       assert(declarer->loaded && declarer->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,
@@ -464,8 +871,10 @@ resolve_field(unresolved_field *ref,
                return false; /* exception */
        }
 
-       /* for non-static accesses we have to check the constraints on the instance type */
-       if ((ref->flags & RESOLVE_STATIC) == 0) {
+       /* for non-static accesses we have to check the constraints on the */
+       /* instance type */
+
+       if (!(ref->flags & RESOLVE_STATIC)) {
 #ifdef RESOLVE_VERBOSE
                fprintf(stderr,"    checking instance types...\n");
 #endif
@@ -473,29 +882,35 @@ resolve_field(unresolved_field *ref,
                if (!resolve_and_check_subtype_set(referer,ref->referermethod,
                                                                                   &(ref->instancetypes),
                                                                                   CLASSREF_OR_CLASSINFO(container),
-                                                                                  false,
-                                                                                  mode,
-                                                                                  resolveLinkageError,&checked))
+                                                                                  false, mode, resolveLinkageError,
+                                                                                  &checked))
                {
                        return false; /* exception */
                }
+
                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) {
-               RESOLVE_ASSERT(fieldtyperef);
+#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,
+                       if (!resolve_and_check_subtype_set(referer, ref->referermethod,
                                                                                           &(ref->valueconstraints),
                                                                                           CLASSREF_OR_CLASSINFO(fieldtyperef),
-                                                                                          false,
-                                                                                          mode,
-                                                                                          resolveLinkageError,&checked))
+                                                                                          false, mode, resolveLinkageError,
+                                                                                          &checked))
                        {
                                return false; /* exception */
                        }
@@ -505,49 +920,127 @@ resolve_field(unresolved_field *ref,
        }
                                                                           
        /* check access rights */
-       if (!is_accessible_member(referer,declarer,fi->flags)) {
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
-                               "field is not accessible XXX add message");
+#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))
+                                                                                  false, mode,
+                                                                                  resolveIllegalAccessError, &checked))
                {
                        return false; /* exception */
                }
+
                if (!checked)
                        return true; /* be lazy */
        }
 
        /* impose loading constraint on field type */
+
        if (fi->type == TYPE_ADR) {
-               RESOLVE_ASSERT(fieldtyperef);
-               if (!classcache_add_constraint(declarer->classloader,referer->classloader,
-                                                                          fieldtyperef->name))
-                       return false; /* exception */
+#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;
 }
 
+/* resolve_field_eager *********************************************************
+   Resolve an unresolved field reference eagerly.
+  
+   IN:
+       ref..............struct containing the reference
+   
+   RETURN VALUE:
+       fieldinfo * to the field, or
+          NULL if an exception has been thrown
+   
+*******************************************************************************/
+
+fieldinfo * resolve_field_eager(unresolved_field *ref)
+{
+       fieldinfo *fi;
+
+       if (!resolve_field(ref,resolveEager,&fi))
+               return NULL;
+
+       return fi;
+}
+
 /******************************************************************************/
 /* METHOD RESOLUTION                                                          */
 /******************************************************************************/
 
-/* for documentation see resolve.h */
-bool
-resolve_method(unresolved_method *ref,
-                          resolve_mode_t mode,
-                          methodinfo **result)
+/* resolve_method **************************************************************
+   Resolve an unresolved method 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_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
 {
        classinfo *referer;
        classinfo *container;
@@ -558,9 +1051,9 @@ resolve_method(unresolved_method *ref,
        int i;
        bool checked;
        
-       RESOLVE_ASSERT(ref);
-       RESOLVE_ASSERT(result);
-       RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
+       assert(ref);
+       assert(result);
+       assert(mode == resolveLazy || mode == resolveEager);
 
 #ifdef RESOLVE_VERBOSE
        unresolved_method_debug_dump(ref,stderr);
@@ -570,11 +1063,11 @@ resolve_method(unresolved_method *ref,
 
        /* the class containing the reference */
        referer = ref->methodref->classref->referer;
-       RESOLVE_ASSERT(referer);
+       assert(referer);
 
        /* first we must resolve the class containg the method */
-       if (!resolve_class(referer,ref->referermethod,
-                                          ref->methodref->classref->name,mode,&container))
+       if (!resolve_class_from_name(referer,ref->referermethod,
+                                          ref->methodref->classref->name,mode,true,true,&container))
        {
                /* the class reference could not be resolved */
                return false; /* exception */
@@ -582,39 +1075,100 @@ resolve_method(unresolved_method *ref,
        if (!container)
                return true; /* be lazy */
 
-       RESOLVE_ASSERT(container);
+       assert(container);
+       assert(container->linked);
 
        /* now we must find the declaration of the method in `container`
         * or one of its superclasses */
 
-       if ((container->flags & ACC_INTERFACE) != 0) {
+       if (container->flags & ACC_INTERFACE) {
                mi = class_resolveinterfacemethod(container,
-                                                                             ref->methodref->name,ref->methodref->descriptor,
-                                                                             referer,true);
-       }
-       else {
+                                                                             ref->methodref->name,
+                                                                                 ref->methodref->descriptor,
+                                                                             referer, true);
+
+       } else {
                mi = class_resolveclassmethod(container,
-                                                                         ref->methodref->name,ref->methodref->descriptor,
-                                                                         referer,true);
+                                                                         ref->methodref->name,
+                                                                         ref->methodref->descriptor,
+                                                                         referer, true);
        }
-       if (!mi)
+
+       if (!mi) {
+               if (mode == resolveLazy) {
+                       /* 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.)           */
+
+                       *exceptionptr = NULL;
+                       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;
-       RESOLVE_ASSERT(declarer);
+       assert(declarer);
+       assert(referer->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,
+               *exceptionptr =
+                       new_exception_message(string_java_lang_IncompatibleClassChangeError,
                                (mi->flags & ACC_STATIC) ? "static method called via instance"
                                                         : "instance method called without instance");
-               return false; /* exception */
+               return false;
        }
 
-       /* for non-static methods we have to check the constraints on the instance type */
-       if ((ref->flags & RESOLVE_STATIC) == 0) {
+       /* have the method params already been parsed? no, do it. */
+
+       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),
@@ -633,16 +1187,16 @@ resolve_method(unresolved_method *ref,
        }
 
        /* check subtype constraints for TYPE_ADR parameters */
-       RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
-       paramtypes = ref->methodref->parseddesc.md->paramtypes;
+
+       assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+       paramtypes = mi->parseddesc->paramtypes;
        
-       for (i=0; i<(mi->paramcount-instancecount); ++i) {
-               if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
-                       RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
+       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].classref),
+                                                       CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
                                                        false,
                                                        mode,
                                                        resolveLinkageError,&checked))
@@ -656,15 +1210,31 @@ resolve_method(unresolved_method *ref,
        }
 
        /* check access rights */
-       if (!is_accessible_member(referer,declarer,mi->flags)) {
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
-                               "method is not accessible XXX add message");
+
+       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 */
        }
 
        /* check protected access */
-       if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
-               /* XXX do we also need to check (referer subclass_of declarer)? */
+
+       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),
@@ -679,9 +1249,11 @@ resolve_method(unresolved_method *ref,
        }
 
        /* impose loading constraints on parameters (including instance) */
-       paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
-       for (i=0; i<mi->paramcount; ++i) {
-               if (mi->paramtypes[i] == TYPE_ADR) {
+
+       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)
@@ -689,43 +1261,71 @@ resolve_method(unresolved_method *ref,
                        else
                                name = paramtypes[i].classref->name;
                        
-                       if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
+                       if (!classcache_add_constraint(referer->classloader,
+                                                                                  declarer->classloader, name))
                                return false; /* exception */
                }
        }
 
        /* impose loading constraing onto return type */
+
        if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
                if (!classcache_add_constraint(referer->classloader,declarer->classloader,
                                ref->methodref->parseddesc.md->returntype.classref->name))
                        return false; /* exception */
        }
 
+#endif /* ENABLE_VERIFIER */
+
        /* succeed */
        *result = mi;
        return true;
 }
 
+/* resolve_method_eager ********************************************************
+   Resolve an unresolved method reference eagerly.
+  
+   IN:
+       ref..............struct containing the reference
+   
+   RETURN VALUE:
+       methodinfo * to the method, or
+          NULL if an exception has been thrown
+   
+*******************************************************************************/
+
+methodinfo * resolve_method_eager(unresolved_method *ref)
+{
+       methodinfo *mi;
+
+       if (!resolve_method(ref,resolveEager,&mi))
+               return NULL;
+
+       return mi;
+}
+
 /******************************************************************************/
 /* CREATING THE DATA STRUCTURES                                               */
 /******************************************************************************/
 
-static bool
-unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
-               unresolved_subtype_set *stset,typeinfo *tinfo,
-               constant_classref *declaredtype)
+#ifdef ENABLE_VERIFIER
+static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
+                                                                                                methodinfo *refmethod,
+                                                                                                unresolved_subtype_set *stset,
+                                                                                                typeinfo *tinfo,
+                                                                                                constant_classref *declaredtype)
 {
        int count;
        int i;
        
-       RESOLVE_ASSERT(stset);
-       RESOLVE_ASSERT(tinfo);
+       assert(stset);
+       assert(tinfo);
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
 #ifdef TYPEINFO_DEBUG
-       /*typeinfo_print(stderr,tinfo,4);*/
-       fprintf(stderr,"\n");
+       typeinfo_print(stderr,tinfo,4);
 #endif
        fprintf(stderr,"    declared type:");utf_fprint(stderr,declaredtype->name);
        fprintf(stderr,"\n");
@@ -758,7 +1358,19 @@ unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
                count = tinfo->merged->count;
                stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
                for (i=0; i<count; ++i) {
-                       stset->subtyperefs[i] = tinfo->merged->list[i];
+                       classref_or_classinfo c = tinfo->merged->list[i];
+                       if (tinfo->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(tinfo->dimension,c.ref);
+                               }
+                               else {
+                                       c.cls = class_multiarray_of(tinfo->dimension,c.cls,false);
+                               }
+                       }
+                       stset->subtyperefs[i] = c;
                }
                stset->subtyperefs[count].any = NULL; /* terminate */
        }
@@ -767,6 +1379,8 @@ unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
                                        ? tinfo->typeclass.ref->name 
                                        : tinfo->typeclass.cls->name) == declaredtype->name)
                {
+                       /* the class names are the same */
+                   /* equality is guaranteed by the loading constraints */
                        goto empty_set;
                }
                else {
@@ -782,19 +1396,78 @@ empty_set:
        UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
        return true;
 }
+#endif /* ENABLE_VERIFIER */
+
+/* create_unresolved_class *****************************************************
+   Create an unresolved_class struct for the given class reference
+  
+   IN:
+          refmethod........the method triggering the resolution (if any)
+          classref.........the class reference
+          valuetype........value type to check against the resolved class
+                                               may be NULL, if no typeinfo is available
+
+   RETURN VALUE:
+       a pointer to a new unresolved_class struct, or
+          NULL if an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+unresolved_class * create_unresolved_class(methodinfo *refmethod,
+                                                                                  constant_classref *classref,
+                                                                                  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);
+       if (refmethod) {
+               fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
+               fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
+       }
+       fprintf(stderr,"    name   : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
+#endif
+
+       ref = NEW(unresolved_class);
+       ref->classref = classref;
+       ref->referermethod = refmethod;
+
+       if (valuetype) {
+               if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
+                                       &(ref->subtypeconstraints),valuetype,classref))
+                       return NULL;
+       }
+       else {
+               UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
+       }
+
+       return ref;
+}
+#endif /* ENABLE_VERIFIER */
+
+/* create_unresolved_field *****************************************************
+   Create an unresolved_field struct for the given field access instruction
+  
+   IN:
+       referer..........the class containing the reference
+          refmethod........the method triggering the resolution (if any)
+          iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
+
+   RETURN VALUE:
+       a pointer to a new unresolved_field struct, or
+          NULL if an exception has been thrown
+
+*******************************************************************************/
 
-unresolved_field *
-create_unresolved_field(classinfo *referer,methodinfo *refmethod,
-                                               instruction *iptr,
-                                               stackelement *stack)
+unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refmethod,
+                                                                                  instruction *iptr)
 {
        unresolved_field *ref;
        constant_FMIref *fieldref = NULL;
-       stackelement *instanceslot = NULL;
-       int type;
-       typeinfo tinfo;
-       typeinfo *tip = NULL;
-       typedesc *fd;
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"create_unresolved_field\n");
@@ -806,34 +1479,30 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod,
        ref = NEW(unresolved_field);
        ref->flags = 0;
        ref->referermethod = refmethod;
+       UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
 
        switch (iptr[0].opc) {
                case ICMD_PUTFIELD:
                        ref->flags |= RESOLVE_PUTFIELD;
-                       instanceslot = stack->prev;
-                       tip = &(stack->typeinfo);
                        fieldref = (constant_FMIref *) iptr[0].val.a;
                        break;
 
                case ICMD_PUTFIELDCONST:
                        ref->flags |= RESOLVE_PUTFIELD;
-                       instanceslot = stack;
-                       fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
+                       fieldref = (constant_FMIref *) iptr[1].val.a;
                        break;
 
                case ICMD_PUTSTATIC:
                        ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
                        fieldref = (constant_FMIref *) iptr[0].val.a;
-                       tip = &(stack->typeinfo);
                        break;
 
                case ICMD_PUTSTATICCONST:
                        ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
-                       fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
+                       fieldref = (constant_FMIref *) iptr[1].val.a;
                        break;
 
                case ICMD_GETFIELD:
-                       instanceslot = stack;
                        fieldref = (constant_FMIref *) iptr[0].val.a;
                        break;
                        
@@ -843,10 +1512,7 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod,
                        break;
        }
        
-       RESOLVE_ASSERT(fieldref);
-       RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
-       fd = fieldref->parseddesc.fd;
-       RESOLVE_ASSERT(fd);
+       assert(fieldref);
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
@@ -858,20 +1524,113 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod,
 #endif
 
        ref->fieldref = fieldref;
+
+       return ref;
+}
+
+/* constrain_unresolved_field **************************************************
+   Record subtype constraints for a field access.
+  
+   IN:
+       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
+
+   RETURN VALUE:
+       true.............everything ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool constrain_unresolved_field(unresolved_field *ref,
+                                                           classinfo *referer, methodinfo *refmethod,
+                                                           instruction *iptr,
+                                                           stackelement *stack)
+{
+       constant_FMIref *fieldref;
+       stackelement *instanceslot = NULL;
+       int type;
+       typeinfo tinfo;
+       typeinfo *tip = NULL;
+       typedesc *fd;
+
+       assert(ref);
+
+       fieldref = ref->fieldref;
+       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]);*/
+#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));
+       fd = fieldref->parseddesc.fd;
+       assert(fd);
+
        /* record subtype constraints for the instance type, if any */
        if (instanceslot) {
                typeinfo *insttip;
-               RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
+
+               /* 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");
+                       return false;
+               }
+               if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
+                       *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
+                       return false;
+               }
                
                if (((ref->flags & RESOLVE_PUTFIELD) != 0) && 
                                TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
-               {   /* XXX clean up */
+               {
+                       /* 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);
-                       classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a 
-                                                                                : refmethod->class; /* XXX classrefs */
-                       RESOLVE_ASSERT(initclass->loaded && initclass->linked);
-                       TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
+
+                       if (ins != NULL) {
+                               *exceptionptr = new_verifyerror(refmethod,"accessing field of uninitialized object");
+                               return false;
+                       }
+                       /* XXX check that class of field == refmethod->class */
+                       initclass = refmethod->class; /* XXX classrefs */
+                       assert(initclass->loaded && initclass->linked);
+                       typeinfo_init_classinfo(&tinfo,initclass);
                        insttip = &tinfo;
                }
                else {
@@ -879,7 +1638,7 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod,
                }
                if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
                                        &(ref->instancetypes),insttip,fieldref->classref))
-                       return NULL;
+                       return false;
        }
        else {
                UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
@@ -892,40 +1651,51 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod,
                        /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
                        tip = &tinfo;
                        if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
-                               TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
+                               assert(class_java_lang_String);
+                               assert(class_java_lang_String->loaded);
+                               assert(class_java_lang_String->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))
-                       return NULL;
+                       return false;
        }
        else {
                UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
        }
 
-       return ref;
+       return true;
 }
+#endif /* ENABLE_VERIFIER */
+
+/* create_unresolved_method ****************************************************
+   Create an unresolved_method struct for the given method invocation
+  
+   IN:
+       referer..........the class containing the reference
+          refmethod........the method triggering the resolution (if any)
+          iptr.............the INVOKE* instruction
+
+   RETURN VALUE:
+       a pointer to a new unresolved_method struct, or
+          NULL if an exception has been thrown
 
-unresolved_method *
-create_unresolved_method(classinfo *referer,methodinfo *refmethod,
-                                                instruction *iptr,
-                                                stackelement *stack)
+*******************************************************************************/
+
+unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *refmethod,
+                                                                                        instruction *iptr)
 {
        unresolved_method *ref;
        constant_FMIref *methodref;
-       stackelement *instanceslot = NULL;
-       stackelement *param;
-       methoddesc *md;
-       typeinfo tinfo;
-       int i,j;
-       int type;
+       bool staticmethod;
 
        methodref = (constant_FMIref *) iptr[0].val.a;
-       RESOLVE_ASSERT(methodref);
-       md = methodref->parseddesc.md;
-       RESOLVE_ASSERT(md);
+       assert(methodref);
+       staticmethod = (iptr[0].opc == ICMD_INVOKESTATIC);
 
 #ifdef RESOLVE_VERBOSE
        fprintf(stderr,"create_unresolved_method\n");
@@ -938,79 +1708,130 @@ create_unresolved_method(classinfo *referer,methodinfo *refmethod,
        /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
 #endif
 
+       /* allocate params if necessary */
+       if (!methodref->parseddesc.md->params)
+               if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
+                                       (staticmethod) ? ACC_STATIC : ACC_NONE))
+                       return NULL;
+
+       /* create the data structure */
        ref = NEW(unresolved_method);
-       ref->flags = 0;
+       ref->flags = ((staticmethod) ? RESOLVE_STATIC : 0)
+                          | ((iptr[0].opc == ICMD_INVOKESPECIAL) ? RESOLVE_SPECIAL : 0);
        ref->referermethod = refmethod;
        ref->methodref = methodref;
        ref->paramconstraints = NULL;
+       UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
 
-       switch (iptr[0].opc) {
-               case ICMD_INVOKESTATIC:
-                       ref->flags |= RESOLVE_STATIC;
-                       break;
-               case ICMD_INVOKEVIRTUAL:
-               case ICMD_INVOKESPECIAL:
-               case ICMD_INVOKEINTERFACE:
-                       break;
-               default:
-                       RESOLVE_ASSERT(false);
-       }
+       return ref;
+}
+
+/* constrain_unresolved_method *************************************************
+   Record subtype constraints for the arguments 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
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool constrain_unresolved_method(unresolved_method *ref,
+                                                                classinfo *referer, methodinfo *refmethod,
+                                                                instruction *iptr,
+                                                                stackelement *stack)
+{
+       constant_FMIref *methodref;
+       stackelement *instanceslot = NULL;
+       stackelement *param;
+       methoddesc *md;
+       typeinfo tinfo;
+       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
+       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]);*/
+#endif
 
        if ((ref->flags & RESOLVE_STATIC) == 0) {
                /* find the instance slot under all the parameter slots on the stack */
                instanceslot = stack;
-               for (i=0; i<md->paramcount; ++i)
+               for (i=1; i<md->paramcount; ++i)
                        instanceslot = instanceslot->prev;
+               instancecount = 1;
+       }
+       else {
+               instancecount = 0;
        }
        
-       RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
+       assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
 
        /* record subtype constraints for the instance type, if any */
        if (instanceslot) {
                typeinfo *tip;
                
-               RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
+               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);
-                       classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a 
-                                                                                : refmethod->class; /* XXX classrefs */
-                       RESOLVE_ASSERT(initclass->loaded && initclass->linked);
-                       TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
+                       classref_or_classinfo initclass = (ins) ? CLASSREF_OR_CLASSINFO(ins[-1].target)
+                                                                                : CLASSREF_OR_CLASSINFO(refmethod->class);
                        tip = &tinfo;
+                       if (!typeinfo_init_class(tip,initclass))
+                               return false;
                }
                else {
                        tip = &(instanceslot->typeinfo);
                }
                if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
                                        &(ref->instancetypes),tip,methodref->classref))
-                       return NULL;
-       }
-       else {
-               UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
+                       return false;
        }
        
        /* record subtype constraints for the parameter types, if any */
        param = stack;
-       for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
-               type = md->paramtypes[i].type;
-               
-               RESOLVE_ASSERT(param);
-               RESOLVE_ASSERT(type == param->type);
-               
+       for (i=md->paramcount-1-instancecount; i>=0; --i, param=param->prev) {
+               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; j>i; --j)
+                               for (j=md->paramcount-1-instancecount; j>i; --j)
                                        UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
                        }
-                       RESOLVE_ASSERT(ref->paramconstraints);
+                       assert(ref->paramconstraints);
                        if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
                                                ref->paramconstraints + i,&(param->typeinfo),
-                                               md->paramtypes[i].classref))
-                               return NULL;
+                                               md->paramtypes[i+instancecount].classref))
+                               return false;
                }
                else {
                        if (ref->paramconstraints)
@@ -1018,15 +1839,16 @@ create_unresolved_method(classinfo *referer,methodinfo *refmethod,
                }
        }
 
-       return ref;
+       return true;
 }
+#endif /* ENABLE_VERIFIER */
 
 /******************************************************************************/
 /* FREEING MEMORY                                                             */
 /******************************************************************************/
 
-inline static void 
-unresolved_subtype_set_free_list(classref_or_classinfo *list)
+#ifdef ENABLE_VERIFIER
+inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
 {
        if (list) {
                classref_or_classinfo *p = list;
@@ -1037,6 +1859,26 @@ unresolved_subtype_set_free_list(classref_or_classinfo *list)
                MFREE(list,classref_or_classinfo,(p - list));
        }
 }
+#endif /* ENABLE_VERIFIER */
+
+/* unresolved_class_free *******************************************************
+   Free the memory used by an unresolved_class
+  
+   IN:
+       ref..............the unresolved_class
+
+*******************************************************************************/
+
+void unresolved_class_free(unresolved_class *ref)
+{
+       assert(ref);
+
+#ifdef ENABLE_VERIFIER
+       unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
+#endif
+       FREE(ref,unresolved_class);
+}
 
 /* unresolved_field_free *******************************************************
  
@@ -1047,13 +1889,14 @@ unresolved_subtype_set_free_list(classref_or_classinfo *list)
 
 *******************************************************************************/
 
-void 
-unresolved_field_free(unresolved_field *ref)
+void unresolved_field_free(unresolved_field *ref)
 {
-       RESOLVE_ASSERT(ref);
+       assert(ref);
 
+#ifdef ENABLE_VERIFIER
        unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
        unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
+#endif
        FREE(ref,unresolved_field);
 }
 
@@ -1066,11 +1909,11 @@ unresolved_field_free(unresolved_field *ref)
 
 *******************************************************************************/
 
-void 
-unresolved_method_free(unresolved_method *ref)
+void unresolved_method_free(unresolved_method *ref)
 {
-       RESOLVE_ASSERT(ref);
+       assert(ref);
 
+#ifdef ENABLE_VERIFIER
        unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
        if (ref->paramconstraints) {
                int i;
@@ -1080,9 +1923,11 @@ unresolved_method_free(unresolved_method *ref)
                        unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
                MFREE(ref->paramconstraints,unresolved_subtype_set,count);
        }
+#endif
        FREE(ref,unresolved_method);
 }
 
+#ifndef NDEBUG
 /******************************************************************************/
 /* DEBUG DUMPS                                                                */
 /******************************************************************************/
@@ -1097,8 +1942,7 @@ unresolved_method_free(unresolved_method *ref)
 
 *******************************************************************************/
 
-void
-unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
+void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
 {
        classref_or_classinfo *p;
        
@@ -1121,6 +1965,33 @@ unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
        }
 }
 
+/* unresolved_class_debug_dump *************************************************
+   Print debug info for unresolved_class to stream
+  
+   IN:
+       ref..............the unresolved_class
+          file.............the stream
+
+*******************************************************************************/
+
+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);
+               fprintf(file,"    refmethod : ");
+               utf_fprint(file,ref->referermethod->name); fputc('\n',file);
+               fprintf(file,"    refmethodd: ");
+               utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
+               fprintf(file,"    classname : ");
+               utf_fprint(file,ref->classref->name); fputc('\n',file);
+               fprintf(file,"    subtypeconstraints:\n");
+               unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
+       }
+}
+
 /* unresolved_field_debug_dump *************************************************
  
    Print debug info for unresolved_field to stream
@@ -1131,16 +2002,15 @@ unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
 
 *******************************************************************************/
 
-void 
-unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
+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);
-               fprintf(file,"    refmethod  : ");
+               fprintf(file,"    refmethod : ");
                utf_fprint(file,ref->referermethod->name); fputc('\n',file);
-               fprintf(file,"    refmethodd : ");
+               fprintf(file,"    refmethodd: ");
                utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
                fprintf(file,"    classname : ");
                utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
@@ -1168,8 +2038,7 @@ unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
 
 *******************************************************************************/
 
-void 
-unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
+void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
 {
        int i;
 
@@ -1177,9 +2046,9 @@ unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
        if (ref) {
                fprintf(file,"    referer   : ");
                utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
-               fprintf(file,"    refmethod  : ");
+               fprintf(file,"    refmethod : ");
                utf_fprint(file,ref->referermethod->name); fputc('\n',file);
-               fprintf(file,"    refmethodd : ");
+               fprintf(file,"    refmethodd: ");
                utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
                fprintf(file,"    classname : ");
                utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
@@ -1204,6 +2073,7 @@ unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
                }
        }
 }
+#endif
 
 /*
  * These are local overrides for various environment variables in Emacs.