* Removed all Id tags.
[cacao.git] / src / vm / resolve.c
index 1a81bb9d66ded8ebcb041e8a507dfb784284ebf9..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 5727 2006-10-09 23:17:56Z edwin $
-
 */
 
 
 
 #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/global.h"
-#include "vm/linker.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/stringlocal.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                                                              */
@@ -104,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);
@@ -173,10 +173,18 @@ bool resolve_class_from_name(classinfo *referer,
 #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;
+                       }
                }
        }
 
@@ -189,19 +197,27 @@ bool resolve_class_from_name(classinfo *referer,
 #endif
        
        /* check access rights of referer to refered class */
+
        if (checkaccess && !access_is_accessible_class(referer,cls)) {
-               int msglen;
-               char *message;
-
-               msglen = utf_bytes(cls->name) + utf_bytes(referer->name) + 100;
-               message = MNEW(char, msglen);
-               strcpy(message, "class is not accessible (");
-               utf_cat_classname(message, cls->name);
-               strcat(message, " from ");
-               utf_cat_classname(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 */
        }
 
@@ -264,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)
@@ -298,6 +317,7 @@ bool resolve_classref_or_classinfo(methodinfo *refmethod,
                                                                   classinfo **result)
 {
        classinfo         *c;
+       classinfo         *referer;
        
        assert(cls.any);
        assert(mode == resolveEager || mode == resolveLazy);
@@ -314,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;
 
@@ -349,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
@@ -397,12 +455,16 @@ bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, class
        }
        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));
@@ -459,9 +521,12 @@ static resolve_result_t resolve_subtype_check(methodinfo *refmethod,
                                                                                          resolve_mode_t mode,
                                                                                          resolve_err_t error)
 {
-       classinfo *subclass;
-       typeinfo subti;
-       typecheck_result r;
+       classinfo        *subclass;
+       typeinfo          subti;
+       typecheck_result  r;
+       char             *msg;
+       s4                msglen;
+       utf              *u;
 
        assert(refmethod);
        assert(subtype.any);
@@ -475,7 +540,7 @@ static resolve_result_t resolve_subtype_check(methodinfo *refmethod,
                /* 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) */
-               *exceptionptr = NULL;
+               exceptions_clear_exception();
                return resolveSucceeded;
        }
        if (!subclass)
@@ -516,27 +581,38 @@ check_again:
        if (!r) {
                /* sub class relationship is false */
 
-               char *message;
-               int msglen;
-
 #if defined(RESOLVE_VERBOSE)
                printf("SUBTYPE CHECK FAILED!\n");
 #endif
 
-               msglen = utf_bytes(subclass->name) + utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype)) + 200;
-               message = MNEW(char, msglen);
-               strcpy(message, (error == resolveIllegalAccessError) ?
-                               "illegal access to protected member ("
-                               : "subtype constraint violated (");
-               utf_cat_classname(message, subclass->name);
-               strcat(message, " is not a subclass of ");
-               utf_cat_classname(message, CLASSREF_OR_CLASSINFO_NAME(supertype));
-               strcat(message, ")");
+               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)
-                       *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
+                       exceptions_throw_illegalaccessexception(u);
                else
-                       *exceptionptr = exceptions_new_linkageerror(message, NULL);
-               MFREE(message, char, msglen);
+                       exceptions_throw_linkageerror(msg, NULL);
+
+               /* ATTENTION: We probably need msg for
+                  exceptions_throw_linkageerror. */
+
+               MFREE(msg, char, msglen);
+
                return resolveFailed; /* exception */
        }
 
@@ -926,6 +1002,32 @@ classinfo * resolve_class_eager(unresolved_class *ref)
 }
 #endif /* ENABLE_VERIFIER */
 
+/* resolve_class_eager_no_access_check *****************************************
+   Resolve an unresolved class reference eagerly. The class is also linked.
+   Access rights are _not_ 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_no_access_check(unresolved_class *ref)
+{
+       classinfo *c;
+
+       if (!resolve_class(ref, resolveEager, false, &c))
+               return NULL;
+
+       return c;
+}
+#endif /* ENABLE_VERIFIER */
+
 /******************************************************************************/
 /* FIELD RESOLUTION                                                           */
 /******************************************************************************/
@@ -961,10 +1063,13 @@ resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
                                                                                           bool isstatic,
                                                                                           bool isput)
 {
-       classinfo *declarer;
-       classinfo *referer;
-       resolve_result_t result;
+       classinfo         *declarer;
+       classinfo         *referer;
+       resolve_result_t   result;
        constant_classref *fieldtyperef;
+       char              *msg;
+       s4                 msglen;
+       utf               *u;
 
        assert(refmethod);
        assert(fieldref);
@@ -990,30 +1095,39 @@ resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
 
        if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
                /* 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");
+               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)) {
-               int msglen;
-               char *message;
-
-               msglen = utf_bytes(declarer->name) + utf_bytes(fi->name) + utf_bytes(referer->name) + 100;
-               message = MNEW(char, msglen);
-               strcpy(message, "field is not accessible (");
-               utf_cat_classname(message, declarer->name);
-               strcat(message, ".");
-               utf_cat(message, fi->name);
-               strcat(message, " from ");
-               utf_cat_classname(message, referer->name);
-               strcat(message, ")");
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
-               MFREE(message,char,msglen);
+               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 */
        }
 
@@ -1177,7 +1291,7 @@ resolve_result_t resolve_field_lazy(methodinfo *refmethod,
                /* 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 resolveDeferred; /* be lazy */
        }
 
@@ -1276,7 +1390,7 @@ 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 */
                }
 
@@ -1441,7 +1555,9 @@ methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
 
                        if (mi == NULL) {
                                /* the spec calls for an AbstractMethodError in this case */
+
                                exceptions_throw_abstractmethoderror();
+
                                return NULL;
                        }
                }
@@ -1476,7 +1592,9 @@ resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
 {
        classinfo *declarer;
        classinfo *referer;
-       methoddesc *md;
+       char      *msg;
+       s4         msglen;
+       utf       *u;
 
        assert(refmethod);
        assert(methodref);
@@ -1494,43 +1612,48 @@ resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
 
        declarer = mi->class;
        assert(declarer);
-       assert(referer->state & CLASS_LINKED);
-
-       md = methodref->parseddesc.md;
-       assert(md);
-       assert(md->params);
 
        /* check static */
 
        if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
                /* 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");
+               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)) {
-               int msglen;
-               char *message;
-
                /* 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;
-               message = MNEW(char, msglen);
-               strcpy(message, "method is not accessible (");
-               utf_cat_classname(message, declarer->name);
-               strcat(message, ".");
-               utf_cat(message, mi->name);
-               utf_cat(message, mi->descriptor);
-               strcat(message," from ");
-               utf_cat_classname(message, referer->name);
-               strcat(message,")");
-               *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
-               MFREE(message, char, msglen);
+
+               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 */
        }
 
@@ -1541,9 +1664,77 @@ resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
 #endif /* defined(ENABLE_VERIFIER) */
 
 
-/* resolve_method_type_checks **************************************************
+/* resolve_method_instance_type_checks *****************************************
 
-   Check parameter types of a method invocation.
+   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
@@ -1551,7 +1742,6 @@ resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
           iptr.............the invoke instruction
           mi...............the methodinfo of the resolved method
           invokestatic.....true if the method is invoked by INVOKESTATIC
-          invokespecial....true if the method is invoked by INVOKESPECIAL
 
    RETURN VALUE:
        resolveSucceeded....everything ok
@@ -1561,16 +1751,13 @@ resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
 *******************************************************************************/
 
 #if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_method_type_checks(jitdata *jd, 
-                                                                                       methodinfo *refmethod,
-                                                                                       instruction *iptr, 
-                                                                                       methodinfo *mi,
-                                                                                       bool invokestatic,
-                                                                                       bool invokespecial)
+resolve_result_t resolve_method_param_type_checks(jitdata *jd, 
+                                                                                                 methodinfo *refmethod,
+                                                                                                 instruction *iptr, 
+                                                                                                 methodinfo *mi,
+                                                                                                 bool invokestatic)
 {
-       varinfo         *instanceslot;
        varinfo         *param;
-       typeinfo         tinfo;
        resolve_result_t result;
        methoddesc      *md;
        typedesc        *paramtypes;
@@ -1578,84 +1765,95 @@ resolve_result_t resolve_method_type_checks(jitdata *jd,
        s4               instancecount;
        s4               i;
 
-       /* for non-static methods we have to check the constraints on the         */
-       /* instance type                                                          */
-
        assert(jd);
 
-       if (invokestatic) {
-               instancecount = 0;
-               instanceslot = NULL;
-       }
-       else {
-               instancecount = 1;
-               instanceslot = VAR(iptr->sx.s23.s2.args[0]);
-       }
+       instancecount = (invokestatic) ? 0 : 1;
 
-       assert((instanceslot && instancecount == 1) || invokestatic);
+       /* check subtype constraints for TYPE_ADR parameters */
 
-       /* record subtype constraints for the instance type, if any */
-       if (instanceslot) {
-               typeinfo *tip;
-
-               assert(instanceslot->type == TYPE_ADR);
-
-               if (invokespecial && TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
-               {   /* XXX clean up */
-                       instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
-                       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 = &(instanceslot->typeinfo);
-               }
+       md = mi->parseddesc;
+       paramtypes = md->paramtypes;
 
-               result = resolve_lazy_subtype_checks(refmethod,
-                                                                                        tip,
-                                                                                        CLASSREF_OR_CLASSINFO(mi->class),
-                                                                                        resolveLinkageError);
-               if (result != resolveSucceeded)
-                       return result;
+       for (i = md->paramcount-1-instancecount; i>=0; --i) {
+               param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+               type = md->paramtypes[i+instancecount].type;
 
-               /* check protected access */
+               assert(param);
+               assert(type == param->type);
 
-               /* XXX use other `declarer` than mi->class? */
-               if (((mi->flags & ACC_PROTECTED) != 0) 
-                               && !SAME_PACKAGE(mi->class, refmethod->class))
-               {
+               if (type == TYPE_ADR) {
                        result = resolve_lazy_subtype_checks(refmethod,
-                                       tip,
-                                       CLASSREF_OR_CLASSINFO(refmethod->class),
-                                       resolveIllegalAccessError);
+                                       &(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;
 
-       for (i = md->paramcount-1-instancecount; i>=0; --i) {
-               param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
-               type = md->paramtypes[i+instancecount].type;
+       param = stack - (md->paramslots - 1 - instancecount);
+
+       for (i = instancecount; i < md->paramcount; ++i) {
+               type = md->paramtypes[i].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),
+                                       CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
                                        resolveLinkageError);
                        if (result != resolveSucceeded)
                                return result;
                }
+
+               param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
        }
 
        /* everything ok */
@@ -1813,7 +2011,7 @@ resolve_result_t resolve_method_lazy(methodinfo *refmethod,
                /* 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 resolveDeferred; /* be lazy */
        }
 
@@ -1932,7 +2130,7 @@ 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 */
                }
 
@@ -2276,7 +2474,6 @@ unresolved_field * resolve_create_unresolved_field(classinfo *referer,
        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);
-       /*printf("    opcode : %d %s\n",iptr->opc,icmd_names[iptr->opc]);*/
 #endif
 
        ref->fieldref = fieldref;
@@ -2328,7 +2525,6 @@ bool resolve_constrain_unresolved_field(unresolved_field *ref,
        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);
-       /*printf("    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
 #endif
 
        assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
@@ -2455,9 +2651,10 @@ unresolved_method * resolve_create_unresolved_method(classinfo *referer,
        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
@@ -2471,28 +2668,20 @@ unresolved_method * resolve_create_unresolved_method(classinfo *referer,
 
 *******************************************************************************/
 
-#ifdef ENABLE_VERIFIER
-bool constrain_unresolved_method(jitdata *jd,
-                                                                        unresolved_method *ref,
-                                                                        classinfo *referer, methodinfo *refmethod,
-                                                                        instruction *iptr)
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
+                                                                                                 methodinfo *refmethod,
+                                                                                                 typeinfo *instanceti,
+                                                                                                 bool invokespecial)
 {
-       constant_FMIref *methodref;
+       constant_FMIref   *methodref;
        constant_classref *instanceref;
-       varinfo *instanceslot = NULL;
-       varinfo *param;
-       methoddesc *md;
-       typeinfo tinfo;
-       int i,j;
-       int type;
-       int instancecount;
+       typeinfo           tinfo;
+       typeinfo          *tip;
 
        assert(ref);
        methodref = ref->methodref;
        assert(methodref);
-       md = methodref->parseddesc.md;
-       assert(md);
-       assert(md->params != NULL);
 
        /* XXX clean this up */
        instanceref = IS_FMIREF_RESOLVED(methodref)
@@ -2500,49 +2689,81 @@ bool constrain_unresolved_method(jitdata *jd,
                : methodref->p.classref;
 
 #ifdef RESOLVE_VERBOSE
-       printf("constrain_unresolved_method\n");
-       printf("    referer: "); class_println(referer);
+       printf("resolve_constrain_unresolved_method_instance\n");
        printf("    rmethod: "); method_println(refmethod);
        printf("    mref   : "); method_methodref_println(methodref);
-       /*printf("    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 = VAR(iptr->sx.s23.s2.args[0]);
-               instancecount = 1;
+       /* 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 {
-               instancecount = 0;
+               tip = instanceti;
        }
 
-       assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
+       if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+                               &(ref->instancetypes),tip,instanceref->name))
+               return false;
+
+       return true;
+}
+#endif /* defined(ENABLE_VERIFIER) */
 
-       /* 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) ? ins[-1].sx.val.c
-                                                                                : 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,instanceref->name))
-                       return false;
-       }
+
+/* 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;
+       varinfo *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\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 */
+
        for (i=md->paramcount-1-instancecount; i>=0; --i) {
                param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
                type = md->paramtypes[i+instancecount].type;
@@ -2557,7 +2778,7 @@ bool constrain_unresolved_method(jitdata *jd,
                                        UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
                        }
                        assert(ref->paramconstraints);
-                       if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
+                       if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
                                                ref->paramconstraints + i,&(param->typeinfo),
                                                md->paramtypes[i+instancecount].classref->name))
                                return false;
@@ -2572,6 +2793,84 @@ bool constrain_unresolved_method(jitdata *jd,
 }
 #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 - (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 = 0; j < i - instancecount; ++j)
+                                       UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
+                       }
+                       assert(ref->paramconstraints);
+                       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                                                             */
 /******************************************************************************/
@@ -2805,6 +3104,7 @@ void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
 }
 #endif /* !defined(NDEBUG) */
 
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
@@ -2818,4 +3118,3 @@ void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
  * End:
  * vim:noexpandtab:sw=4:ts=4:
  */
-