* merged default branch into jitcache-arm-x86 branch
authorRobert Schuster <robertschuster@fsfe.org>
Fri, 10 Oct 2008 14:18:16 +0000 (16:18 +0200)
committerRobert Schuster <robertschuster@fsfe.org>
Fri, 10 Oct 2008 14:18:16 +0000 (16:18 +0200)
--HG--
branch : jitcache-arm-x86
rename : src/vm/class.c => src/vm/class.cpp
rename : src/vm/class.h => src/vm/class.hpp
rename : src/vm/resolve.c => src/vm/resolve.cpp

14 files changed:
1  2 
src/vm/class.cpp
src/vm/class.hpp
src/vm/jit/arm/patcher.c
src/vm/jit/builtin.cpp
src/vm/jit/codegen-common.cpp
src/vm/jit/i386/patcher.c
src/vm/jit/jit.cpp
src/vm/jit/patcher-common.cpp
src/vm/options.c
src/vm/options.h
src/vm/references.h
src/vm/resolve.cpp
src/vm/statistics.c
src/vm/vm.cpp

index 0000000000000000000000000000000000000000,6444cbb6750449a5b869fa7416a54b6dd12311c1..1e479529b61ce124f11a7ff33fa9b02a83a24cfe
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2455 +1,2464 @@@
+ /* src/vm/class.cpp - class related functions
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #include "config.h"
+ #include <assert.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "vm/types.h"
+ #include "arch.h"
+ #include "mm/memory.h"
+ #include "native/llni.h"
+ #include "threads/lock.hpp"
+ #include "threads/mutex.hpp"
+ #include "toolbox/logging.h"
+ #include "vm/array.hpp"
+ #include "vm/jit/builtin.hpp"
+ #include "vm/class.hpp"
+ #include "vm/classcache.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/javaobjects.hpp"
++#include "vm/jit/jitcache.hpp"
+ #include "vm/linker.h"
+ #include "vm/loader.hpp"
+ #include "vm/options.h"
+ #include "vm/resolve.hpp"
+ #if defined(ENABLE_STATISTICS)
+ # include "vm/statistics.h"
+ #endif
+ #include "vm/suck.hpp"
+ #include "vm/utf8.h"
+ #include "vm/jit/asmpart.h"
+ /* class_set_packagename *******************************************************
+    Derive the package name from the class name and store it in the
+    struct.
+    An internal package name consists of the package name plus the
+    trailing '/', e.g. "java/lang/".
+    For classes in the unnamed package, the package name is set to
+    NULL.
+ *******************************************************************************/
+ void class_set_packagename(classinfo *c)
+ {
+       char *p;
+       char *start;
+       p     = UTF_END(c->name) - 1;
+       start = c->name->text;
+       if (c->name->text[0] == '[') {
+               /* Set packagename of arrays to the element's package. */
+               for (; *start == '['; start++);
+               /* Skip the 'L' in arrays of references. */
+               if (*start == 'L')
+                       start++;
+       }
+       /* Search for last '/'. */
+       for (; (p > start) && (*p != '/'); --p);
+       /* If we found a '/' we set the package name plus the trailing
+          '/'.  Otherwise we set the packagename to NULL. */
+       if (p > start)
+               c->packagename = utf_new(start, p - start + 1);
+       else
+               c->packagename = NULL;
+ }
+ /* class_create_classinfo ******************************************************
+    Create a new classinfo struct. The class name is set to the given utf *,
+    most other fields are initialized to zero.
+    Note: classname may be NULL. In this case a not-yet-named classinfo is
+          created. The name must be filled in later and class_set_packagename
+                must be called after that.
+ *******************************************************************************/
+ classinfo *class_create_classinfo(utf *classname)
+ {
+       classinfo *c;
+ #if defined(ENABLE_STATISTICS)
+       if (opt_stat)
+               size_classinfo += sizeof(classinfo);
+ #endif
+       /* we use a safe name for temporarily unnamed classes */
+       if (classname == NULL)
+               classname = utf_not_named_yet;
+ #if !defined(NDEBUG)
+       if (initverbose)
+               log_message_utf("Creating class: ", classname);
+ #endif
+ #if !defined(ENABLE_GC_BOEHM)
+       c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
+       /*c = NEW(classinfo);
+       MZERO(c, classinfo, 1);*/
+ #else
+       c = GCNEW_UNCOLLECTABLE(classinfo, 1);
+       /* GCNEW_UNCOLLECTABLE clears the allocated memory */
+ #endif
+       c->name = classname;
+       /* Set the header.vftbl of all loaded classes to the one of
+        java.lang.Class, so Java code can use a class as object. */
+       if (class_java_lang_Class != NULL)
+               if (class_java_lang_Class->vftbl != NULL)
+                       c->object.header.vftbl = class_java_lang_Class->vftbl;
+ #if defined(ENABLE_JAVASE)
+       /* check if the class is a reference class and flag it */
+       if (classname == utf_java_lang_ref_SoftReference) {
+               c->flags |= ACC_CLASS_REFERENCE_SOFT;
+       }
+       else if (classname == utf_java_lang_ref_WeakReference) {
+               c->flags |= ACC_CLASS_REFERENCE_WEAK;
+       }
+       else if (classname == utf_java_lang_ref_PhantomReference) {
+               c->flags |= ACC_CLASS_REFERENCE_PHANTOM;
+       }
+ #endif
+       if (classname != utf_not_named_yet)
+               class_set_packagename(c);
++#if defined (ENABLE_JITCACHE)
++    c->cache_file_fd = 0;
++#endif
+       c->object.header.lockword.init();
+       return c;
+ }
+ /* class_postset_header_vftbl **************************************************
+    Set the header.vftbl of all classes created before java.lang.Class
+    was linked.  This is necessary that Java code can use a class as
+    object.
+ *******************************************************************************/
+ void class_postset_header_vftbl(void)
+ {
+       classinfo *c;
+       u4 slot;
+       classcache_name_entry *nmen;
+       classcache_class_entry *clsen;
+       assert(class_java_lang_Class);
+       for (slot = 0; slot < hashtable_classcache.size; slot++) {
+               nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+               for (; nmen; nmen = nmen->hashlink) {
+                       /* iterate over all class entries */
+                       for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+                               c = clsen->classobj;
+                               /* now set the the vftbl */
+                               if (c->object.header.vftbl == NULL)
+                                       c->object.header.vftbl = class_java_lang_Class->vftbl;
+                       }
+               }
+       }
+ }
+ /* class_define ****************************************************************
+    Calls the loader and defines a class in the VM.
+ *******************************************************************************/
+ classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
+ {
+       classinfo   *c;
+       classinfo   *r;
+       classbuffer *cb;
+       if (name != NULL) {
+               /* check if this class has already been defined */
+               c = classcache_lookup_defined_or_initiated(cl, name);
+               if (c != NULL) {
+                       exceptions_throw_linkageerror("duplicate class definition: ", c);
+                       return NULL;
+               }
+       } 
+       /* create a new classinfo struct */
+       c = class_create_classinfo(name);
+ #if defined(ENABLE_STATISTICS)
+       /* measure time */
+       if (opt_getloadingtime)
+               loadingtime_start();
+ #endif
+       /* build a classbuffer with the given data */
+       cb = NEW(classbuffer);
+       cb->clazz = c;
+       cb->size  = length;
+       cb->data  = data;
+       cb->pos   = cb->data;
+       /* preset the defining classloader */
+       c->classloader = cl;
+       /* load the class from this buffer */
+       r = load_class_from_classbuffer(cb);
+       /* free memory */
+       FREE(cb, classbuffer);
+ #if defined(ENABLE_STATISTICS)
+       /* measure time */
+       if (opt_getloadingtime)
+               loadingtime_stop();
+ #endif
+       if (r == NULL) {
+               /* If return value is NULL, we had a problem and the class is
+                  not loaded.  Now free the allocated memory, otherwise we
+                  could run into a DOS. */
+               class_free(c);
+               return NULL;
+       }
+ #if defined(ENABLE_JAVASE)
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       /* Store the protection domain. */
+       c->protectiondomain = pd;
+ # endif
+ #endif
+       /* Store the newly defined class in the class cache. This call
+          also checks whether a class of the same name has already been
+          defined by the same defining loader, and if so, replaces the
+          newly created class by the one defined earlier. */
+       /* Important: The classinfo given to classcache_store must be
+                     fully prepared because another thread may return
+                     this pointer after the lookup at to top of this
+                     function directly after the class cache lock has
+                     been released. */
+       c = classcache_store(cl, c, true);
+       return c;
+ }
+ /* class_load_attribute_sourcefile *********************************************
+    SourceFile_attribute {
+        u2 attribute_name_index;
+        u4 attribute_length;
+          u2 sourcefile_index;
+    }
+ *******************************************************************************/
+ static bool class_load_attribute_sourcefile(classbuffer *cb)
+ {
+       classinfo *c;
+       u4         attribute_length;
+       u2         sourcefile_index;
+       utf       *sourcefile;
+       /* get classinfo */
+       c = cb->clazz;
+       /* check buffer size */
+       if (!suck_check_classbuffer_size(cb, 4 + 2))
+               return false;
+       /* check attribute length */
+       attribute_length = suck_u4(cb);
+       if (attribute_length != 2) {
+               exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+               return false;
+       }
+       /* there can be no more than one SourceFile attribute */
+       if (c->sourcefile != NULL) {
+               exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
+               return false;
+       }
+       /* get sourcefile */
+       sourcefile_index = suck_u2(cb);
+       sourcefile = (utf*) class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
+       if (sourcefile == NULL)
+               return false;
+       /* store sourcefile */
+       c->sourcefile = sourcefile;
+       return true;
+ }
+ /* class_load_attribute_enclosingmethod ****************************************
+    EnclosingMethod_attribute {
+        u2 attribute_name_index;
+        u4 attribute_length;
+          u2 class_index;
+          u2 method_index;
+    }
+ *******************************************************************************/
+ #if defined(ENABLE_JAVASE)
+ static bool class_load_attribute_enclosingmethod(classbuffer *cb)
+ {
+       classinfo             *c;
+       u4                     attribute_length;
+       u2                     class_index;
+       u2                     method_index;
+       classref_or_classinfo  cr;
+       constant_nameandtype  *cn;
+       /* get classinfo */
+       c = cb->clazz;
+       /* check buffer size */
+       if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+               return false;
+       /* check attribute length */
+       attribute_length = suck_u4(cb);
+       if (attribute_length != 4) {
+               exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+               return false;
+       }
+       /* there can be no more than one EnclosingMethod attribute */
+       if (c->enclosingmethod != NULL) {
+               exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
+               return false;
+       }
+       /* get class index */
+       class_index = suck_u2(cb);
+       cr.ref = (constant_classref*) innerclass_getconstant(c, class_index, CONSTANT_Class);
+       /* get method index */
+       method_index = suck_u2(cb);
+       cn = (constant_nameandtype*) innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
+       /* store info in classinfo */
+       c->enclosingclass.any = cr.any;
+       c->enclosingmethod    = cn;
+       return true;
+ }
+ #endif /* defined(ENABLE_JAVASE) */
+ /* class_load_attributes *******************************************************
+    Read attributes from ClassFile.
+    attribute_info {
+        u2 attribute_name_index;
+        u4 attribute_length;
+        u1 info[attribute_length];
+    }
+    InnerClasses_attribute {
+        u2 attribute_name_index;
+        u4 attribute_length;
+    }
+ *******************************************************************************/
+ bool class_load_attributes(classbuffer *cb)
+ {
+       classinfo             *c;
+       uint16_t               attributes_count;
+       uint16_t               attribute_name_index;
+       utf                   *attribute_name;
+       innerclassinfo        *info;
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *name;
+       uint16_t               flags;
+       int                    i, j;
+       c = cb->clazz;
+       /* get attributes count */
+       if (!suck_check_classbuffer_size(cb, 2))
+               return false;
+       attributes_count = suck_u2(cb);
+       for (i = 0; i < attributes_count; i++) {
+               /* get attribute name */
+               if (!suck_check_classbuffer_size(cb, 2))
+                       return false;
+               attribute_name_index = suck_u2(cb);
+               attribute_name =
+                       (utf*) class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
+               if (attribute_name == NULL)
+                       return false;
+               if (attribute_name == utf_InnerClasses) {
+                       /* InnerClasses */
+                       if (c->innerclass != NULL) {
+                               exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
+                               return false;
+                       }
+                               
+                       if (!suck_check_classbuffer_size(cb, 4 + 2))
+                               return false;
+                       /* skip attribute length */
+                       suck_u4(cb);
+                       /* number of records */
+                       c->innerclasscount = suck_u2(cb);
+                       if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+                               return false;
+                       /* allocate memory for innerclass structure */
+                       c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
+                       for (j = 0; j < c->innerclasscount; j++) {
+                               /* The innerclass structure contains a class with an encoded
+                                  name, its defining scope, its simple name and a bitmask of
+                                  the access flags. */
+                                                               
+                               info = c->innerclass + j;
+                               inner.ref = (constant_classref*) innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               outer.ref = (constant_classref*) innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+                               name      = (utf*) innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+                               flags     = suck_u2(cb);
+                               /* If the current inner-class is the currently loaded
+                                  class check for some special flags. */
+                               if (inner.ref->name == c->name) {
+                                       /* If an inner-class is not a member, its
+                                          outer-class is NULL. */
+                                       if (outer.ref != NULL) {
+                                               c->flags |= ACC_CLASS_MEMBER;
+                                               /* A member class doesn't have an
+                                                  EnclosingMethod attribute, so set the
+                                                  enclosing-class to be the same as the
+                                                  declaring-class. */
+                                               c->declaringclass = outer;
+                                               c->enclosingclass = outer;
+                                       }
+                                       /* If an inner-class is anonymous, its name is
+                                          NULL. */
+                                       if (name == NULL)
+                                               c->flags |= ACC_CLASS_ANONYMOUS;
+                               }
+                               info->inner_class = inner;
+                               info->outer_class = outer;
+                               info->name        = name;
+                               info->flags       = flags;
+                       }
+               }
+               else if (attribute_name == utf_SourceFile) {
+                       /* SourceFile */
+                       if (!class_load_attribute_sourcefile(cb))
+                               return false;
+               }
+ #if defined(ENABLE_JAVASE)
+               else if (attribute_name == utf_EnclosingMethod) {
+                       /* EnclosingMethod */
+                       if (!class_load_attribute_enclosingmethod(cb))
+                               return false;
+               }
+               else if (attribute_name == utf_Signature) {
+                       /* Signature */
+                       if (!loader_load_attribute_signature(cb, &(c->signature)))
+                               return false;
+               }
+ #endif
+ #if defined(ENABLE_ANNOTATIONS)
+               else if (attribute_name == utf_RuntimeVisibleAnnotations) {
+                       /* RuntimeVisibleAnnotations */
+                       if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
+                               return false;
+               }
+               else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+                       /* RuntimeInvisibleAnnotations */
+                       if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
+                               return false;
+               }
+ #endif
+               else {
+                       /* unknown attribute */
+                       if (!loader_skip_attribute_body(cb))
+                               return false;
+               }
+       }
+       return true;
+ }
+ /* class_freepool **************************************************************
+       Frees all resources used by this classes Constant Pool.
+ *******************************************************************************/
+ static void class_freecpool(classinfo *c)
+ {
+       u4 idx;
+       u4 tag;
+       void* info;
+       
+       if (c->cptags && c->cpinfos) {
+               for (idx = 0; idx < c->cpcount; idx++) {
+                       tag = c->cptags[idx];
+                       info = c->cpinfos[idx];
+               
+                       if (info != NULL) {
+                               switch (tag) {
+                               case CONSTANT_Fieldref:
+                               case CONSTANT_Methodref:
+                               case CONSTANT_InterfaceMethodref:
+                                       FREE(info, constant_FMIref);
+                                       break;
+                               case CONSTANT_Integer:
+                                       FREE(info, constant_integer);
+                                       break;
+                               case CONSTANT_Float:
+                                       FREE(info, constant_float);
+                                       break;
+                               case CONSTANT_Long:
+                                       FREE(info, constant_long);
+                                       break;
+                               case CONSTANT_Double:
+                                       FREE(info, constant_double);
+                                       break;
+                               case CONSTANT_NameAndType:
+                                       FREE(info, constant_nameandtype);
+                                       break;
+                               }
+                       }
+               }
+       }
+       if (c->cptags)
+               MFREE(c->cptags, u1, c->cpcount);
+       if (c->cpinfos)
+               MFREE(c->cpinfos, void*, c->cpcount);
+ }
+ /* class_getconstant ***********************************************************
+    Retrieves the value at position 'pos' of the constantpool of a
+    class. If the type of the value is other than 'ctype', an error is
+    thrown.
+ *******************************************************************************/
+ void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
+ {
+       /* check index and type of constantpool entry */
+       /* (pos == 0 is caught by type comparison) */
+       if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
+               exceptions_throw_classformaterror(c, "Illegal constant pool index");
+               return NULL;
+       }
+       return c->cpinfos[pos];
+ }
+ /* innerclass_getconstant ******************************************************
+    Like class_getconstant, but if cptags is ZERO, null is returned.
+       
+ *******************************************************************************/
+ void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
+ {
+       /* invalid position in constantpool */
+       if (pos >= c->cpcount) {
+               exceptions_throw_classformaterror(c, "Illegal constant pool index");
+               return NULL;
+       }
+       /* constantpool entry of type 0 */      
+       if (c->cptags[pos] == 0)
+               return NULL;
+       /* check type of constantpool entry */
+       if (c->cptags[pos] != ctype) {
+               exceptions_throw_classformaterror(c, "Illegal constant pool index");
+               return NULL;
+       }
+               
+       return c->cpinfos[pos];
+ }
+ /* class_free ******************************************************************
+    Frees all resources used by the class.
+ *******************************************************************************/
+ void class_free(classinfo *c)
+ {
+       s4 i;
+       vftbl_t *v;
++#if defined(ENABLE_JITCACHE)
++/* TODO: Find a way around the linker problem */
++/*    jitcache_freeclass(c);*/
++#endif
++
+       class_freecpool(c);
+       if (c->interfaces != NULL)
+               MFREE(c->interfaces, classinfo*, c->interfacescount);
+       if (c->fields) {
+               for (i = 0; i < c->fieldscount; i++)
+                       field_free(&(c->fields[i]));
+               MFREE(c->fields, fieldinfo, c->fieldscount);
+       }
+       
+       if (c->methods) {
+               for (i = 0; i < c->methodscount; i++)
+                       method_free(&(c->methods[i]));
+               MFREE(c->methods, methodinfo, c->methodscount);
+       }
+       if ((v = c->vftbl) != NULL) {
+               if (v->arraydesc)
+                       mem_free(v->arraydesc,sizeof(arraydescriptor));
+               
+               for (i = 0; i < v->interfacetablelength; i++) {
+                       MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
+               }
+               MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
+               i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
+                   sizeof(methodptr*) * (v->interfacetablelength -
+                                        (v->interfacetablelength > 0));
+               v = (vftbl_t*) (((methodptr*) v) -
+                                               (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
+               mem_free(v, i);
+       }
+       if (c->innerclass)
+               MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
+       /*      if (c->classvftbl)
+               mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
+       
+ /*    GCFREE(c); */
+ }
+ /* get_array_class *************************************************************
+    Returns the array class with the given name for the given
+    classloader, or NULL if an exception occurred.
+    Note: This function does eager loading. 
+ *******************************************************************************/
+ static classinfo *get_array_class(utf *name,classloader_t *initloader,
+                                                                                       classloader_t *defloader,bool link)
+ {
+       classinfo *c;
+       
+       /* lookup this class in the classcache */
+       c = classcache_lookup(initloader,name);
+       if (!c)
+               c = classcache_lookup_defined(defloader,name);
+       if (!c) {
+               /* we have to create it */
+               c = class_create_classinfo(name);
+               c = load_newly_created_array(c,initloader);
+               if (c == NULL)
+                       return NULL;
+       }
+       assert(c);
+       assert(c->state & CLASS_LOADED);
+       assert(c->classloader == defloader);
+       if (link && !(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+       assert(!link || (c->state & CLASS_LINKED));
+       return c;
+ }
+ /* class_array_of **************************************************************
+    Returns an array class with the given component class. The array
+    class is dynamically created if neccessary.
+ *******************************************************************************/
+ classinfo *class_array_of(classinfo *component, bool link)
+ {
+       classloader_t     *cl;
+     s4                 namelen;
+     char              *namebuf;
+       utf               *u;
+       classinfo         *c;
+       cl = component->classloader;
+     /* Assemble the array class name */
+     namelen = component->name->blength;
+     
+     if (component->name->text[0] == '[') {
+         /* the component is itself an array */
+         namebuf = MNEW(char, namelen + 1);
+         namebuf[0] = '[';
+         MCOPY(namebuf + 1, component->name->text, char, namelen);
+         namelen++;
+     }
+       else {
+         /* the component is a non-array class */
+         namebuf = MNEW(char, namelen + 3);
+         namebuf[0] = '[';
+         namebuf[1] = 'L';
+         MCOPY(namebuf + 2, component->name->text, char, namelen);
+         namebuf[2 + namelen] = ';';
+         namelen += 3;
+     }
+       u = utf_new(namebuf, namelen);
+       MFREE(namebuf, char, namelen);
+       c = get_array_class(u, cl, cl, link);
+       return c;
+ }
+ /* class_multiarray_of *********************************************************
+    Returns an array class with the given dimension and element class.
+    The array class is dynamically created if neccessary.
+ *******************************************************************************/
+ classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
+ {
+     s4 namelen;
+     char *namebuf;
+       classinfo *c;
+       if (dim < 1) {
+               log_text("Invalid array dimension requested");
+               assert(0);
+       }
+     /* Assemble the array class name */
+     namelen = element->name->blength;
+     
+     if (element->name->text[0] == '[') {
+         /* the element is itself an array */
+         namebuf = MNEW(char, namelen + dim);
+         memcpy(namebuf + dim, element->name->text, namelen);
+         namelen += dim;
+     }
+     else {
+         /* the element is a non-array class */
+         namebuf = MNEW(char, namelen + 2 + dim);
+         namebuf[dim] = 'L';
+         memcpy(namebuf + dim + 1, element->name->text, namelen);
+         namelen += (2 + dim);
+         namebuf[namelen - 1] = ';';
+     }
+       memset(namebuf, '[', dim);
+       utf* u = utf_new(namebuf, namelen);
+       MFREE(namebuf, char, namelen);
+       c = get_array_class(u,
+                                               element->classloader,
+                                               element->classloader,
+                                               link);
+       return c;
+ }
+ /* class_lookup_classref *******************************************************
+    Looks up the constant_classref for a given classname in the classref
+    tables of a class.
+    IN:
+        cls..............the class containing the reference
+          name.............the name of the class refered to
+     RETURN VALUE:
+          a pointer to a constant_classref, or 
+          NULL if the reference was not found
+    
+ *******************************************************************************/
+ constant_classref *class_lookup_classref(classinfo *cls, utf *name)
+ {
+       constant_classref *ref;
+       extra_classref *xref;
+       int count;
+       assert(cls);
+       assert(name);
+       assert(!cls->classrefcount || cls->classrefs);
+       
+       /* first search the main classref table */
+       count = cls->classrefcount;
+       ref = cls->classrefs;
+       for (; count; --count, ++ref)
+               if (ref->name == name)
+                       return ref;
+       /* next try the list of extra classrefs */
+       for (xref = cls->extclassrefs; xref; xref = xref->next) {
+               if (xref->classref.name == name)
+                       return &(xref->classref);
+       }
+       /* not found */
+       return NULL;
+ }
+ /* class_get_classref **********************************************************
+    Returns the constant_classref for a given classname.
+    IN:
+        cls..............the class containing the reference
+          name.............the name of the class refered to
+    RETURN VALUE:
+        a pointer to a constant_classref (never NULL)
+    NOTE:
+        The given name is not checked for validity!
+    
+ *******************************************************************************/
+ constant_classref *class_get_classref(classinfo *cls, utf *name)
+ {
+       constant_classref *ref;
+       extra_classref *xref;
+       assert(cls);
+       assert(name);
+       ref = class_lookup_classref(cls,name);
+       if (ref)
+               return ref;
+       xref = NEW(extra_classref);
+       CLASSREF_INIT(xref->classref,cls,name);
+       xref->next = cls->extclassrefs;
+       cls->extclassrefs = xref;
+       return &(xref->classref);
+ }
+ /* class_get_self_classref *****************************************************
+    Returns the constant_classref to the class itself.
+    IN:
+        cls..............the class containing the reference
+    RETURN VALUE:
+        a pointer to a constant_classref (never NULL)
+ *******************************************************************************/
+ constant_classref *class_get_self_classref(classinfo *cls)
+ {
+       /* XXX this should be done in a faster way. Maybe always make */
+       /* the classref of index 0 a self reference.                  */
+       return class_get_classref(cls,cls->name);
+ }
+ /* class_get_classref_multiarray_of ********************************************
+    Returns an array type reference with the given dimension and element class
+    reference.
+    IN:
+        dim..............the requested dimension
+                           dim must be in [1;255]. This is NOT checked!
+          ref..............the component class reference
+    RETURN VALUE:
+        a pointer to the class reference for the array type
+    NOTE:
+        The referer of `ref` is used as the referer for the new classref.
+ *******************************************************************************/
+ constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
+ {
+     s4 namelen;
+     char *namebuf;
+       constant_classref *cr;
+       assert(ref);
+       assert(dim >= 1 && dim <= 255);
+     /* Assemble the array class name */
+     namelen = ref->name->blength;
+     
+     if (ref->name->text[0] == '[') {
+         /* the element is itself an array */
+         namebuf = MNEW(char, namelen + dim);
+         memcpy(namebuf + dim, ref->name->text, namelen);
+         namelen += dim;
+     }
+     else {
+         /* the element is a non-array class */
+         namebuf = MNEW(char, namelen + 2 + dim);
+         namebuf[dim] = 'L';
+         memcpy(namebuf + dim + 1, ref->name->text, namelen);
+         namelen += (2 + dim);
+         namebuf[namelen - 1] = ';';
+     }
+       memset(namebuf, '[', dim);
+       utf* u = utf_new(namebuf, namelen);
+       MFREE(namebuf, char, namelen);
+     cr = class_get_classref(ref->referer, u);
+       return cr;
+ }
+ /* class_get_classref_component_of *********************************************
+    Returns the component classref of a given array type reference
+    IN:
+        ref..............the array type reference
+    RETURN VALUE:
+        a reference to the component class, or
+          NULL if `ref` is not an object array type reference
+    NOTE:
+        The referer of `ref` is used as the referer for the new classref.
+ *******************************************************************************/
+ constant_classref *class_get_classref_component_of(constant_classref *ref)
+ {
+       s4 namelen;
+       char *name;
+       
+       assert(ref);
+       name = ref->name->text;
+       if (*name++ != '[')
+               return NULL;
+       
+       namelen = ref->name->blength - 1;
+       if (*name == 'L') {
+               name++;
+               namelen -= 2;
+       }
+       else if (*name != '[') {
+               return NULL;
+       }
+     return class_get_classref(ref->referer, utf_new(name, namelen));
+ }
+ /* class_findmethod ************************************************************
+       
+    Searches a 'classinfo' structure for a method having the given name
+    and descriptor. If descriptor is NULL, it is ignored.
+ *******************************************************************************/
+ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+ {
+       methodinfo *m;
+       s4          i;
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+               if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
+                       return m;
+       }
+       return NULL;
+ }
+ /* class_resolvemethod *********************************************************
+       
+    Searches a class and it's super classes for a method.
+    Superinterfaces are *not* searched.
+ *******************************************************************************/
+ methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+ {
+       methodinfo *m;
+       while (c) {
+               m = class_findmethod(c, name, desc);
+               if (m)
+                       return m;
+               /* JVM Specification bug: 
+                  It is important NOT to resolve special <init> and <clinit>
+                  methods to super classes or interfaces; yet, this is not
+                  explicited in the specification.  Section 5.4.3.3 should be
+                  updated appropriately.  */
+               if (name == utf_init || name == utf_clinit)
+                       return NULL;
+               c = c->super;
+       }
+       return NULL;
+ }
+ /* class_resolveinterfacemethod_intern *****************************************
+    Internally used helper function. Do not use this directly.
+ *******************************************************************************/
+ static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
+                                                                                                          utf *name, utf *desc)
+ {
+       methodinfo *m;
+       s4          i;
+       /* try to find the method in the class */
+       m = class_findmethod(c, name, desc);
+       if (m != NULL)
+               return m;
+       /* No method found?  Try the super interfaces. */
+       for (i = 0; i < c->interfacescount; i++) {
+               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+               if (m != NULL)
+                       return m;
+       }
+       /* no method found */
+       return NULL;
+ }
+ /* class_resolveclassmethod ****************************************************
+       
+    Resolves a reference from REFERER to a method with NAME and DESC in
+    class C.
+    If the method cannot be resolved the return value is NULL. If
+    EXCEPT is true *exceptionptr is set, too.
+ *******************************************************************************/
+ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
+                                                                        classinfo *referer, bool throwexception)
+ {
+       classinfo  *cls;
+       methodinfo *m;
+       s4          i;
+ /*    if (c->flags & ACC_INTERFACE) { */
+ /*            if (throwexception) */
+ /*                    *exceptionptr = */
+ /*                            new_exception(string_java_lang_IncompatibleClassChangeError); */
+ /*            return NULL; */
+ /*    } */
+       /* try class c and its superclasses */
+       cls = c;
+       m = class_resolvemethod(cls, name, desc);
+       if (m != NULL)
+               goto found;
+       /* Try the super interfaces. */
+       for (i = 0; i < c->interfacescount; i++) {
+               m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+               if (m != NULL)
+                       goto found;
+       }
+       
+       if (throwexception)
+               exceptions_throw_nosuchmethoderror(c, name, desc);
+       return NULL;
+  found:
+       if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
+               if (throwexception)
+                       exceptions_throw_abstractmethoderror();
+               return NULL;
+       }
+       /* XXX check access rights */
+       return m;
+ }
+ /* class_resolveinterfacemethod ************************************************
+    Resolves a reference from REFERER to a method with NAME and DESC in
+    interface C.
+    If the method cannot be resolved the return value is NULL. If
+    EXCEPT is true *exceptionptr is set, too.
+ *******************************************************************************/
+ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
+                                                                                classinfo *referer, bool throwexception)
+ {
+       methodinfo *mi;
+       if (!(c->flags & ACC_INTERFACE)) {
+               if (throwexception)
+                       exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
+               return NULL;
+       }
+       mi = class_resolveinterfacemethod_intern(c, name, desc);
+       if (mi != NULL)
+               return mi;
+       /* try class java.lang.Object */
+       mi = class_findmethod(class_java_lang_Object, name, desc);
+       if (mi != NULL)
+               return mi;
+       if (throwexception)
+               exceptions_throw_nosuchmethoderror(c, name, desc);
+       return NULL;
+ }
+ /* class_findfield *************************************************************
+       
+    Searches for field with specified name and type in a classinfo
+    structure. If no such field is found NULL is returned.
+ *******************************************************************************/
+ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
+ {
+       s4 i;
+       for (i = 0; i < c->fieldscount; i++)
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
+                       return &(c->fields[i]);
+       if (c->super != NULL)
+               return class_findfield(c->super, name, desc);
+       return NULL;
+ }
+ /* class_findfield_approx ******************************************************
+       
+    Searches in 'classinfo'-structure for a field with the specified
+    name.
+ *******************************************************************************/
+  
+ fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
+ {
+       for (int32_t i = 0; i < c->fieldscount; i++) {
+               fieldinfo* f = &(c->fields[i]);
+               if (f->name == name)
+                       return f;
+       }
+       // Field not found.
+       exceptions_throw_nosuchfielderror(c, name);
+       return NULL;
+ }
+ /****************** Function: class_resolvefield_int ***************************
+     This is an internally used helper function. Do not use this directly.
+       Tries to resolve a field having the given name and type.
+     If the field cannot be resolved, NULL is returned.
+ *******************************************************************************/
+ static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
+ {
+       fieldinfo *fi;
+       s4         i;
+       /* search for field in class c */
+       for (i = 0; i < c->fieldscount; i++) { 
+               if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+                       return &(c->fields[i]);
+               }
+     }
+       /* Try super interfaces recursively. */
+       for (i = 0; i < c->interfacescount; i++) {
+               fi = class_resolvefield_int(c->interfaces[i], name, desc);
+               if (fi != NULL)
+                       return fi;
+       }
+       /* Try super class. */
+       if (c->super != NULL)
+               return class_resolvefield_int(c->super, name, desc);
+       /* not found */
+       return NULL;
+ }
+ /********************* Function: class_resolvefield ***************************
+       
+       Resolves a reference from REFERER to a field with NAME and DESC in class C.
+     If the field cannot be resolved, an exception is thrown and the
+     return value is NULL.
+ *******************************************************************************/
+ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer)
+ {
+       fieldinfo *fi;
+       fi = class_resolvefield_int(c, name, desc);
+       if (!fi) {
+               exceptions_throw_nosuchfielderror(c, name);
+               return NULL;
+       }
+       /* XXX check access rights */
+       return fi;
+ }
+ /* class_issubclass ************************************************************
+    Checks if sub is a descendant of super.
+       
+ *******************************************************************************/
+ bool class_issubclass(classinfo *sub, classinfo *super)
+ {
+       classinfo *c;
+       c = sub;
+       for (;;) {
+               /* We reached java/lang/Object and did not find the requested
+                  super class. */
+               if (c == NULL)
+                       return false;
+               /* We found the requested super class. */
+               if (c == super)
+                       return true;
+               c = c->super;
+       }
+ }
+ /* class_isanysubclass *********************************************************
+    Checks a subclass relation between two classes. Implemented
+    interfaces are interpreted as super classes.
+    Return value: 1 ... sub is subclass of super
+                  0 ... otherwise
+ *******************************************************************************/
+ bool class_isanysubclass(classinfo *sub, classinfo *super)
+ {
+       uint32_t diffval;
+       bool     result;
+       /* This is the trivial case. */
+       if (sub == super)
+               return true;
+       /* Primitive classes are only subclasses of themselves. */
+       if (class_is_primitive(sub) || class_is_primitive(super))
+               return false;
+       /* Check for interfaces. */
+       if (super->flags & ACC_INTERFACE) {
+               result = (sub->vftbl->interfacetablelength > super->index) &&
+                       (sub->vftbl->interfacetable[-super->index] != NULL);
+       }
+       else {
+               /* java.lang.Object is the only super class of any
+                  interface. */
+               if (sub->flags & ACC_INTERFACE)
+                       return (super == class_java_lang_Object);
+               linker_classrenumber_mutex->lock();
+               diffval = sub->vftbl->baseval - super->vftbl->baseval;
+               result  = diffval <= (uint32_t) super->vftbl->diffval;
+               linker_classrenumber_mutex->unlock();
+       }
+       return result;
+ }
+ /* class_is_assignable_from ****************************************************
+    Return whether an instance of the "from" class parameter would be
+    an instance of this class "to" as well.
+    ARGUMENTS:
+        to ..... class
+          from ... class
+    RETURN:
+        true .... is assignable
+          false ... is not assignable
+ *******************************************************************************/
+ bool class_is_assignable_from(classinfo *to, classinfo *from)
+ {
+       if (!(to->state & CLASS_LINKED))
+               if (!link_class(to))
+                       return false;
+       if (!(from->state & CLASS_LINKED))
+               if (!link_class(from))
+                       return false;
+       return class_isanysubclass(from, to);
+ }
+ /* class_is_instance ***********************************************************
+    Return if the given Java object is an instance of the given class.
+    ARGUMENTS:
+        c ... class
+          h ... Java object
+    RETURN:
+        true .... is instance
+          false ... is not instance
+ *******************************************************************************/
+ bool class_is_instance(classinfo *c, java_handle_t *h)
+ {
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return false;
+       return builtin_instanceof(h, c);
+ }
+ /* class_get_componenttype *****************************************************
+    Return the component class of the given class.  If the given class
+    is not an array, return NULL.
+ *******************************************************************************/
+ classinfo *class_get_componenttype(classinfo *c)
+ {
+       classinfo       *component;
+       arraydescriptor *ad;
+       
+       /* XXX maybe we could find a way to do this without linking. */
+       /* This way should be safe and easy, however.                */
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+       ad = c->vftbl->arraydesc;
+       
+       if (ad == NULL)
+               return NULL;
+       
+       if (ad->arraytype == ARRAYTYPE_OBJECT)
+               component = ad->componentvftbl->clazz;
+       else
+               component = Primitive::get_class_by_type(ad->arraytype);
+               
+       return component;
+ }
+ /* class_get_declaredclasses ***************************************************
+    Return an array of declared classes of the given class.
+ *******************************************************************************/
+ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
+ {
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *outername;
+       int                    declaredclasscount;  /* number of declared classes */
+       int                    pos;                     /* current declared class */
+       java_handle_objectarray_t *oa;               /* array of declared classes */
+       int                    i;
+       classinfo             *ic;
+       declaredclasscount = 0;
+       if (!class_is_primitive(c) && !class_is_array(c)) {
+               /* Determine number of declared classes. */
+               for (i = 0; i < c->innerclasscount; i++) {
+                       /* Get outer-class.  If the inner-class is not a member
+                          class, the outer-class is NULL. */
+                       outer = c->innerclass[i].outer_class;
+                       if (outer.any == NULL)
+                               continue;
+                       /* Check if outer-class is a classref or a real class and
+                get the class name from the structure. */
+                       outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+                       /* Outer class is this class. */
+                       if ((outername == c->name) &&
+                               ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
+                               declaredclasscount++;
+               }
+       }
+       /* Allocate Class[] and check for OOM. */
+       oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
+       if (oa == NULL)
+               return NULL;
+       for (i = 0, pos = 0; i < c->innerclasscount; i++) {
+               inner = c->innerclass[i].inner_class;
+               outer = c->innerclass[i].outer_class;
+               /* Get outer-class.  If the inner-class is not a member class,
+                  the outer-class is NULL. */
+               if (outer.any == NULL)
+                       continue;
+               /* Check if outer_class is a classref or a real class and get
+                  the class name from the structure. */
+               outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+               /* Outer class is this class. */
+               if ((outername == c->name) &&
+                       ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
+                       ic = resolve_classref_or_classinfo_eager(inner, false);
+                       if (ic == NULL)
+                               return NULL;
+                       if (!(ic->state & CLASS_LINKED))
+                               if (!link_class(ic))
+                                       return NULL;
+                       LLNI_array_direct(oa, pos++) = (java_object_t *) ic;
+               }
+       }
+       return oa;
+ }
+ /**
+  * Return an array of declared constructors of the given class.
+  *
+  * @param c          class to get the constructors of
+  * @param publicOnly show only public fields
+  *
+  * @return array of java.lang.reflect.Constructor
+  */
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
+ {
+       methodinfo*                m;
+       java_handle_objectarray_t* oa;
+       int                        count;
+       int                        index;
+       int                        i;
+       /* Determine number of constructors. */
+       count = 0;
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init))
+                       count++;
+       }
+       /* Create array of constructors. */
+       oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
+       if (oa == NULL)
+               return NULL;
+       /* Get the constructors and store them in the array. */
+       for (i = 0, index = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+                       (m->name == utf_init)) {
+                       // Create a java.lang.reflect.Constructor object.
+                       java_lang_reflect_Constructor rc(m);
+                       /* Store object into array. */
+                       array_objectarray_element_set(oa, index, rc.get_handle());
+                       index++;
+               }
+       }
+       return oa;
+ }
+ #endif
+ /* class_get_declaredfields ****************************************************
+    Return an array of declared fields of the given class.
+    ARGUMENTS:
+        c ............ class to get the fields of
+          publicOnly ... show only public fields
+    RETURN:
+        array of java.lang.reflect.Field
+ *******************************************************************************/
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
+ {
+       java_handle_objectarray_t *oa;
+       fieldinfo                 *f;
+       int                        count;
+       int                        index;
+       int                        i;
+       /* Determine number of fields. */
+       count = 0;
+       for (i = 0; i < c->fieldscount; i++)
+               if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
+                       count++;
+       /* Create array of fields. */
+       oa = builtin_anewarray(count, class_java_lang_reflect_Field);
+       if (oa == NULL)
+               return NULL;
+       /* Get the fields and store them in the array. */
+       for (i = 0, index = 0; i < c->fieldscount; i++) {
+               f = &(c->fields[i]);
+               if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+                       // Create a java.lang.reflect.Field object.
+                       java_lang_reflect_Field rf(f);
+                       /* Store object into array. */
+                       array_objectarray_element_set(oa, index, rf.get_handle());
+                       index++;
+               }
+       }
+       return oa;
+ }
+ #endif
+ /* class_get_declaredmethods ***************************************************
+    Return an array of declared methods of the given class.
+    ARGUMENTS:
+        c ............ class to get the methods of
+          publicOnly ... show only public methods
+    RETURN:
+        array of java.lang.reflect.Method
+ *******************************************************************************/
+ #if defined(ENABLE_JAVASE)
+ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
+ {
+       java_handle_objectarray_t *oa;         /* result: array of Method-objects */
+       methodinfo                *m;     /* the current method to be represented */
+       int                        count;
+       int                        index;
+       int                        i;
+       /* JOWENN: array classes do not declare methods according to mauve
+          test.  It should be considered, if we should return to my old
+          clone method overriding instead of declaring it as a member
+          function. */
+       if (class_is_array(c))
+               return builtin_anewarray(0, class_java_lang_reflect_Method);
+       /* Determine number of methods. */
+       count = 0;
+       for (i = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+                       ((m->name != utf_init) && (m->name != utf_clinit)) &&
+                       !(m->flags & ACC_MIRANDA))
+                       count++;
+       }
+       /* Create array of methods. */
+       oa = builtin_anewarray(count, class_java_lang_reflect_Method);
+       if (oa == NULL)
+               return NULL;
+       /* Get the methods and store them in the array. */
+       for (i = 0, index = 0; i < c->methodscount; i++) {
+               m = &(c->methods[i]);
+               if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) && 
+                       ((m->name != utf_init) && (m->name != utf_clinit)) &&
+                       !(m->flags & ACC_MIRANDA)) {
+                       // Create java.lang.reflect.Method object.
+                       java_lang_reflect_Method rm(m);
+                       /* Store object into array. */
+                       array_objectarray_element_set(oa, index, rm.get_handle());
+                       index++;
+               }
+       }
+       return oa;
+ }
+ #endif
+ /* class_get_declaringclass ****************************************************
+    If the class or interface given is a member of another class,
+    return the declaring class.  For array and primitive classes return
+    NULL.
+ *******************************************************************************/
+ classinfo *class_get_declaringclass(classinfo *c)
+ {
+       classref_or_classinfo  cr;
+       classinfo             *dc;
+       /* Get declaring class. */
+       cr = c->declaringclass;
+       if (cr.any == NULL)
+               return NULL;
+       /* Resolve the class if necessary. */
+       if (IS_CLASSREF(cr)) {
+ /*            dc = resolve_classref_eager(cr.ref); */
+               dc = resolve_classref_or_classinfo_eager(cr, true);
+               if (dc == NULL)
+                       return NULL;
+               /* Store the resolved class in the class structure. */
+               cr.cls = dc;
+       }
+       dc = cr.cls;
+       return dc;
+ }
+ /* class_get_enclosingclass ****************************************************
+    Return the enclosing class for the given class.
+ *******************************************************************************/
+ classinfo *class_get_enclosingclass(classinfo *c)
+ {
+       classref_or_classinfo  cr;
+       classinfo             *ec;
+       /* Get enclosing class. */
+       cr = c->enclosingclass;
+       if (cr.any == NULL)
+               return NULL;
+       /* Resolve the class if necessary. */
+       if (IS_CLASSREF(cr)) {
+ /*            ec = resolve_classref_eager(cr.ref); */
+               ec = resolve_classref_or_classinfo_eager(cr, true);
+               if (ec == NULL)
+                       return NULL;
+               /* Store the resolved class in the class structure. */
+               cr.cls = ec;
+       }
+       ec = cr.cls;
+       return ec;
+ }
+ /**
+  * Return the enclosing constructor as java.lang.reflect.Constructor
+  * object for the given class.
+  *
+  * @param c class to return the enclosing constructor for
+  *
+  * @return java.lang.reflect.Constructor object of the enclosing
+  * constructor
+  */
+ #if defined(ENABLE_JAVASE)
+ java_handle_t* class_get_enclosingconstructor(classinfo *c)
+ {
+       methodinfo*    m;
+       m = class_get_enclosingmethod_raw(c);
+       if (m == NULL)
+               return NULL;
+       /* Check for <init>. */
+       if (m->name != utf_init)
+               return NULL;
+       // Create a java.lang.reflect.Constructor object.
+       java_lang_reflect_Constructor rc(m);
+       return rc.get_handle();
+ }
+ #endif
+ /* class_get_enclosingmethod ***************************************************
+    Return the enclosing method for the given class.
+    IN:
+        c ... class to return the enclosing method for
+    RETURN:
+        methodinfo of the enclosing method
+ *******************************************************************************/
+ methodinfo *class_get_enclosingmethod_raw(classinfo *c)
+ {
+       constant_nameandtype *cn;
+       classinfo            *ec;
+       methodinfo           *m;
+       /* get enclosing class and method */
+       ec = class_get_enclosingclass(c);
+       cn = c->enclosingmethod;
+       /* check for enclosing class and method */
+       if (ec == NULL)
+               return NULL;
+       if (cn == NULL)
+               return NULL;
+       /* find method in enclosing class */
+       m = class_findmethod(ec, cn->name, cn->descriptor);
+       if (m == NULL) {
+               exceptions_throw_internalerror("Enclosing method doesn't exist");
+               return NULL;
+       }
+       return m;
+ }
+ /**
+  * Return the enclosing method as java.lang.reflect.Method object for
+  * the given class.
+  *
+  * @param c class to return the enclosing method for
+  *
+  * @return java.lang.reflect.Method object of the enclosing method
+  */
+ #if defined(ENABLE_JAVASE)
+ java_handle_t* class_get_enclosingmethod(classinfo *c)
+ {
+       methodinfo*    m;
+       m = class_get_enclosingmethod_raw(c);
+       if (m == NULL)
+               return NULL;
+       /* check for <init> */
+       if (m->name == utf_init)
+               return NULL;
+       // Create a java.lang.reflect.Method object.
+       java_lang_reflect_Method rm(m);
+       return rm.get_handle();
+ }
+ #endif
+ /* class_get_interfaces ********************************************************
+    Return an array of interfaces of the given class.
+ *******************************************************************************/
+ java_handle_objectarray_t *class_get_interfaces(classinfo *c)
+ {
+       classinfo                 *ic;
+       java_handle_objectarray_t *oa;
+       u4                         i;
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+       oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
+       if (oa == NULL)
+               return NULL;
+       for (i = 0; i < c->interfacescount; i++) {
+               ic = c->interfaces[i];
+               LLNI_array_direct(oa, i) = (java_object_t *) ic;
+       }
+       return oa;
+ }
+ /* class_get_annotations *******************************************************
+    Get the unparsed declared annotations in a byte array
+    of the given class.
+    IN:
+        c........the class of which the annotations should be returned
+    RETURN VALUE:
+        The unparsed declared annotations in a byte array
+        (or NULL if there aren't any).
+ *******************************************************************************/
+ java_handle_bytearray_t *class_get_annotations(classinfo *c)
+ {
+ #if defined(ENABLE_ANNOTATIONS)
+       java_handle_t *annotations; /* unparsed annotations */
+       LLNI_classinfo_field_get(c, annotations, annotations);
+       return (java_handle_bytearray_t*)annotations;
+ #else
+       return NULL;
+ #endif
+ }
+ /* class_get_modifiers *********************************************************
+    Get the modifier flags of the given class.
+    IN:
+        c....the class of which the modifier flags should be returned
+          ignoreInnerClassesAttrib
+    RETURN VALUE:
+        modifier flags
+ *******************************************************************************/
+ int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
+ {
+       classref_or_classinfo  inner;
+       classref_or_classinfo  outer;
+       utf                   *innername;
+       int                    i;
+       if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
+               /* search for passed class as inner class */
+               for (i = 0; i < c->innerclasscount; i++) {
+                       inner = c->innerclass[i].inner_class;
+                       outer = c->innerclass[i].outer_class;
+                       /* Check if inner is a classref or a real class and get
+                the name of the structure */
+                       innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
+                       /* innerclass is this class */
+                       if (innername == c->name) {
+                               /* has the class actually an outer class? */
+                               if (outer.any)
+                                       /* return flags got from the outer class file */
+                                       return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
+                               else
+                                       return c->flags & ACC_CLASS_REFLECT_MASK;
+                       }
+               }
+       }
+       /* passed class is no inner class or it was not requested */
+       return c->flags & ACC_CLASS_REFLECT_MASK;
+ }
+ /* class_get_signature *********************************************************
+    Return the signature of the given class.  For array and primitive
+    classes return NULL.
+ *******************************************************************************/
+ #if defined(ENABLE_JAVASE)
+ utf *class_get_signature(classinfo *c)
+ {
+       /* For array and primitive classes return NULL. */
+       if (class_is_array(c) || class_is_primitive(c))
+               return NULL;
+       return c->signature;
+ }
+ #endif
+ /* class_printflags ************************************************************
+    Prints flags of a class.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_printflags(classinfo *c)
+ {
+       if (c == NULL) {
+               printf("NULL");
+               return;
+       }
+       if (c->flags & ACC_PUBLIC)       printf(" PUBLIC");
+       if (c->flags & ACC_PRIVATE)      printf(" PRIVATE");
+       if (c->flags & ACC_PROTECTED)    printf(" PROTECTED");
+       if (c->flags & ACC_STATIC)       printf(" STATIC");
+       if (c->flags & ACC_FINAL)        printf(" FINAL");
+       if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+       if (c->flags & ACC_VOLATILE)     printf(" VOLATILE");
+       if (c->flags & ACC_TRANSIENT)    printf(" TRANSIENT");
+       if (c->flags & ACC_NATIVE)       printf(" NATIVE");
+       if (c->flags & ACC_INTERFACE)    printf(" INTERFACE");
+       if (c->flags & ACC_ABSTRACT)     printf(" ABSTRACT");
+ }
+ #endif
+ /* class_print *****************************************************************
+    Prints classname plus flags.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_print(classinfo *c)
+ {
+       if (c == NULL) {
+               printf("NULL");
+               return;
+       }
+       utf_display_printable_ascii(c->name);
+       class_printflags(c);
+ }
+ #endif
+ /* class_classref_print ********************************************************
+    Prints classname plus referer class.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_classref_print(constant_classref *cr)
+ {
+       if (cr == NULL) {
+               printf("NULL");
+               return;
+       }
+       utf_display_printable_ascii(cr->name);
+       printf("(ref.by ");
+       if (cr->referer)
+               class_print(cr->referer);
+       else
+               printf("NULL");
+       printf(")");
+ }
+ #endif
+ /* class_println ***************************************************************
+    Prints classname plus flags and new line.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_println(classinfo *c)
+ {
+       class_print(c);
+       printf("\n");
+ }
+ #endif
+ /* class_classref_println ******************************************************
+    Prints classname plus referer class and new line.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_classref_println(constant_classref *cr)
+ {
+       class_classref_print(cr);
+       printf("\n");
+ }
+ #endif
+ /* class_classref_or_classinfo_print *******************************************
+    Prints classname plus referer class.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_classref_or_classinfo_print(classref_or_classinfo c)
+ {
+       if (c.any == NULL) {
+               printf("(classref_or_classinfo) NULL");
+               return;
+       }
+       if (IS_CLASSREF(c))
+               class_classref_print(c.ref);
+       else
+               class_print(c.cls);
+ }
+ #endif
+ /* class_classref_or_classinfo_println *****************************************
+    Prints classname plus referer class and a newline.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_classref_or_classinfo_println(classref_or_classinfo c)
+ {
+       class_classref_or_classinfo_print(c);
+       printf("\n");
+ }
+ #endif
+ /* class_showconstantpool ******************************************************
+    Dump the constant pool of the given class to stdout.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_showconstantpool (classinfo *c) 
+ {
+       u4 i;
+       void* e;
+       printf ("---- dump of constant pool ----\n");
+       for (i=0; i<c->cpcount; i++) {
+               printf ("#%d:  ", (int) i);
+               
+               e = c -> cpinfos [i];
+               if (e) {
+                       
+                       switch (c -> cptags [i]) {
+                       case CONSTANT_Class:
+                               printf ("Classreference -> ");
+                               utf_display_printable_ascii ( ((constant_classref*)e) -> name );
+                               break;
+                       case CONSTANT_Fieldref:
+                               printf ("Fieldref -> ");
+                               field_fieldref_print((constant_FMIref *) e);
+                               break;
+                       case CONSTANT_Methodref:
+                               printf ("Methodref -> ");
+                               method_methodref_print((constant_FMIref *) e);
+                               break;
+                       case CONSTANT_InterfaceMethodref:
+                               printf ("InterfaceMethod -> ");
+                               method_methodref_print((constant_FMIref *) e);
+                               break;
+                       case CONSTANT_String:
+                               printf ("String -> ");
+                               utf_display_printable_ascii ((utf*) e);
+                               break;
+                       case CONSTANT_Integer:
+                               printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
+                               break;
+                       case CONSTANT_Float:
+                               printf ("Float -> %f", ((constant_float*)e) -> value);
+                               break;
+                       case CONSTANT_Double:
+                               printf ("Double -> %f", ((constant_double*)e) -> value);
+                               break;
+                       case CONSTANT_Long:
+                               printf ("Long -> %ld", (long int) ((constant_long*)e) -> value);
+                               break;
+                       case CONSTANT_NameAndType:
+                               {
+                                       constant_nameandtype *cnt = (constant_nameandtype *) e;
+                                       printf ("NameAndType: ");
+                                       utf_display_printable_ascii (cnt->name);
+                                       printf (" ");
+                                       utf_display_printable_ascii (cnt->descriptor);
+                               }
+                               break;
+                       case CONSTANT_Utf8:
+                               printf ("Utf8 -> ");
+                               utf_display_printable_ascii ((utf*) e);
+                               break;
+                       default: 
+                               log_text("Invalid type of ConstantPool-Entry");
+                               assert(0);
+                       }
+               }
+               printf ("\n");
+       }
+ }
+ #endif /* !defined(NDEBUG) */
+ /* class_showmethods ***********************************************************
+    Dump info about the fields and methods of the given class to stdout.
+ *******************************************************************************/
+ #if !defined(NDEBUG)
+ void class_showmethods (classinfo *c)
+ {
+       s4 i;
+       
+       printf("--------- Fields and Methods ----------------\n");
+       printf("Flags: ");
+       class_printflags(c);
+       printf("\n");
+       printf("This: ");
+       utf_display_printable_ascii(c->name);
+       printf("\n");
+       if (c->super) {
+               printf("Super: ");
+               utf_display_printable_ascii(c->super->name);
+               printf ("\n");
+       }
+       printf("Index: %d\n", c->index);
+       
+       printf("Interfaces:\n");        
+       for (i = 0; i < c->interfacescount; i++) {
+               printf("   ");
+               utf_display_printable_ascii(c->interfaces[i]->name);
+               printf (" (%d)\n", c->interfaces[i]->index);
+       }
+       printf("Fields:\n");
+       for (i = 0; i < c->fieldscount; i++)
+               field_println(&(c->fields[i]));
+       printf("Methods:\n");
+       for (i = 0; i < c->methodscount; i++) {
+               methodinfo *m = &(c->methods[i]);
+               if (!(m->flags & ACC_STATIC))
+                       printf("vftblindex: %d   ", m->vftblindex);
+               method_println(m);
+       }
+       printf ("Virtual function table:\n");
+       for (i = 0; i < c->vftbl->vftbllength; i++)
+               printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]));
+ }
+ #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
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 0000000000000000000000000000000000000000,c82e4bf244092e56f767483fe2c2715f29f0b559..f643fd357850d1398b12e49b132475afa0b220e7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,460 +1,462 @@@
 -
+ /* src/vm/class.hpp - class related functions header
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #ifndef _CLASS_HPP
+ #define _CLASS_HPP
+ /* forward typedefs ***********************************************************/
+ typedef struct classinfo      classinfo; 
+ typedef struct innerclassinfo innerclassinfo;
+ typedef struct extra_classref extra_classref;
+ #include "config.h"
+ #include <stdint.h>
+ #include "vm/types.h"
+ #if defined(ENABLE_JAVASE)
+ # include "vm/annotation.h"
+ #endif
+ #include "vm/field.hpp"
+ #include "vm/global.h"
+ #include "vm/linker.h"
+ #include "vm/loader.hpp"
+ #include "vm/method.h"
+ #include "vm/references.h"
+ #include "vm/string.hpp"
+ #include "vm/utf8.h"
+ /* class state defines ********************************************************/
+ #define CLASS_LOADING         0x0001
+ #define CLASS_LOADED          0x0002
+ #define CLASS_LINKING         0x0004
+ #define CLASS_LINKED          0x0008
+ #define CLASS_INITIALIZING    0x0010
+ #define CLASS_INITIALIZED     0x0020
+ #define CLASS_ERROR           0x0040
+ /* some macros ****************************************************************/
+ #define CLASS_IS_OR_ALMOST_INITIALIZED(c) \
+     (((c)->state & CLASS_INITIALIZING) || ((c)->state & CLASS_INITIALIZED))
+ /* classinfo ******************************************************************/
+ /* We define this dummy structure of java_lang_Class so we can
+    bootstrap cacaoh without needing a java_lang_Class.h file.  Whether
+    the size of the dummy structure is big enough is checked during
+    runtime in vm_create. */
+ typedef struct {
+       java_object_t      header;
+ #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+       intptr_t           padding[4];
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       intptr_t           padding[19];
+ #elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+       intptr_t           padding[3];
+ #else
+ # error unknown classpath configuration
+ #endif
+ } dummy_java_lang_Class;
+ struct classinfo {                /* class structure                          */
+       dummy_java_lang_Class object;
+       s4          flags;            /* ACC flags                                */
+       utf        *name;             /* class name                               */
+       s4          cpcount;          /* number of entries in constant pool       */
+       u1         *cptags;           /* constant pool tags                       */
+       void*      *cpinfos;          /* pointer to constant pool info structures */
+       s4          classrefcount;    /* number of symbolic class references      */
+       constant_classref *classrefs; /* table of symbolic class references       */
+       extra_classref *extclassrefs; /* additional classrefs                     */
+       s4          parseddescsize;   /* size of the parsed descriptors block     */
+       u1         *parseddescs;      /* parsed descriptors                       */
+       classinfo  *super;            /* super class                              */
+       classinfo  *sub;              /* sub class pointer                        */
+       classinfo  *nextsub;          /* pointer to next class in sub class list  */
+       int32_t     interfacescount;  /* number of interfaces                     */
+       classinfo **interfaces;       /* super interfaces                         */
+       int32_t     fieldscount;      /* number of fields                         */
+       fieldinfo  *fields;           /* field table                              */
+       int32_t     methodscount;     /* number of methods                        */
+       methodinfo *methods;          /* method table                             */
+       s4          state;            /* current class state                      */
+       s4          index;            /* hierarchy depth (classes) or index       */
+                                     /* (interfaces)                             */
+       s4          instancesize;     /* size of an instance of this class        */
+       vftbl_t    *vftbl;            /* pointer to virtual function table        */
+       methodinfo *finalizer;        /* finalizer method                         */
+       u2          innerclasscount;  /* number of inner classes                  */
+       innerclassinfo *innerclass;
+       classref_or_classinfo  declaringclass;
+       classref_or_classinfo  enclosingclass;  /* enclosing class                */
+       constant_nameandtype  *enclosingmethod; /* enclosing method               */
+       utf        *packagename;      /* full name of the package                 */
+       utf        *sourcefile;       /* SourceFile attribute                     */
+ #if defined(ENABLE_JAVASE)
+       utf        *signature;        /* Signature attribute                      */
+ #if defined(ENABLE_ANNOTATIONS)
+       /* All the annotation attributes are NULL (and not a zero length array)   */
+       /* if there is nothing.                                                   */
+       java_object_t *annotations;   /* annotations of this class                */
+       
+       java_object_t *method_annotations; /* array of annotations of the methods */
+       java_object_t *method_parameterannotations; /* array of parameter         */
+                                     /* annotations of the methods               */
+       java_object_t *method_annotationdefaults; /* array of annotation default  */
+                                     /* values of the methods                    */
+       java_object_t *field_annotations; /* array of annotations of the fields   */
+ #endif
+ #endif
+       classloader_t *classloader;       /* NULL for bootstrap classloader         */
+ #if defined(ENABLE_JAVASE)
+ # if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+       java_object_t      *protectiondomain;
+       java_objectarray_t *signers;
+ # endif
+ #endif
++#if defined(ENABLE_JITCACHE)
++      int         cache_file_fd;
++#endif
+ };
+ /* innerclassinfo *************************************************************/
+ struct innerclassinfo {
+       classref_or_classinfo inner_class; /* inner class pointer                 */
+       classref_or_classinfo outer_class; /* outer class pointer                 */
+       utf                  *name;        /* innerclass name                     */
+       s4                    flags;       /* ACC flags                           */
+ };
+ /* extra_classref **************************************************************
+    for classrefs not occurring within descriptors
+ *******************************************************************************/
+ struct extra_classref {
+       extra_classref    *next;
+       constant_classref  classref;
+ };
+ /* inline functions ***********************************************************/
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ /**
+  * Returns the classname of the class, where slashes ('/') are
+  * replaced by dots ('.').
+  *
+  * @param c class to get name of
+  * @return classname
+  */
+ inline static java_handle_t* class_get_classname(classinfo* c)
+ {
+       java_handle_t *s;
+       /* Create a java string. */
+       s = javastring_new_slash_to_dot(c->name);
+       return s;
+ }
+ /* class_is_primitive **********************************************************
+    Checks if the given class is a primitive class.
+ *******************************************************************************/
+ static inline bool class_is_primitive(classinfo *c)
+ {
+       if (c->flags & ACC_CLASS_PRIMITIVE)
+               return true;
+       return false;
+ }
+ /* class_is_anonymousclass *****************************************************
+    Checks if the given class is an anonymous class.
+ *******************************************************************************/
+ static inline bool class_is_anonymousclass(classinfo *c)
+ {
+       if (c->flags & ACC_CLASS_ANONYMOUS)
+               return true;
+       return false;
+ }
+ /* class_is_array **************************************************************
+    Checks if the given class is an array class.
+ *******************************************************************************/
+ static inline bool class_is_array(classinfo *c)
+ {
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return false;
+       return (c->vftbl->arraydesc != NULL);
+ }
+ /* class_is_interface **********************************************************
+    Checks if the given class is an interface.
+ *******************************************************************************/
+ static inline bool class_is_interface(classinfo *c)
+ {
+       if (c->flags & ACC_INTERFACE)
+               return true;
+       return false;
+ }
+ /* class_is_localclass *********************************************************
+    Checks if the given class is a local class.
+ *******************************************************************************/
+ static inline bool class_is_localclass(classinfo *c)
+ {
+       if ((c->enclosingmethod != NULL) && !class_is_anonymousclass(c))
+               return true;
+       return false;
+ }
+ /* class_is_memberclass ********************************************************
+    Checks if the given class is a member class.
+ *******************************************************************************/
+ static inline bool class_is_memberclass(classinfo *c)
+ {
+       if (c->flags & ACC_CLASS_MEMBER)
+               return true;
+       return false;
+ }
+ /* class_get_classloader *******************************************************
+    Return the classloader of the given class.
+ *******************************************************************************/
+ static inline classloader_t *class_get_classloader(classinfo *c)
+ {
+       classloader_t *cl;
+       cl = c->classloader;
+       /* The classloader may be NULL. */
+       return cl;
+ }
+ /* class_get_superclass ********************************************************
+    Return the super class of the given class.
+ *******************************************************************************/
+ static inline classinfo *class_get_superclass(classinfo *c)
+ {
+       /* For interfaces we return NULL. */
+       if (c->flags & ACC_INTERFACE)
+               return NULL;
+       /* For java/lang/Object, primitive-type and Void classes c->super
+          is NULL and we return NULL. */
+       return c->super;
+ }
+ /* function prototypes ********************************************************/
+ classinfo *class_create_classinfo(utf *u);
+ void       class_postset_header_vftbl(void);
+ classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd);
+ void       class_set_packagename(classinfo *c);
+ bool       class_load_attributes(classbuffer *cb);
+ /* retrieve constantpool element */
+ void* class_getconstant(classinfo *c, u4 pos, u4 ctype);
+ void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype);
+ /* frees all resources used by the class */
+ void class_free(classinfo *);
+ /* return an array class with the given component class */
+ classinfo *class_array_of(classinfo *component,bool link);
+ /* return an array class with the given dimension and element class */
+ classinfo *class_multiarray_of(s4 dim, classinfo *element,bool link);
+ /* return a classref for the given class name */
+ /* (does a linear search!)                    */
+ constant_classref *class_lookup_classref(classinfo *cls,utf *name);
+ /* return a classref for the given class name */
+ /* (does a linear search!)                    */
+ constant_classref *class_get_classref(classinfo *cls,utf *name);
+ /* return a classref to the class itself */
+ /* (does a linear search!)                    */
+ constant_classref *class_get_self_classref(classinfo *cls);
+ /* return a classref for an array with the given dimension of with the */
+ /* given component type */
+ constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref);
+ /* return a classref for the component type of the given array type */
+ constant_classref *class_get_classref_component_of(constant_classref *ref);
+ /* get a class' field by name and descriptor */
+ fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc);
+ /* search 'classinfo'-structure for a field with the specified name */
+ fieldinfo *class_findfield_by_name(classinfo *c, utf *name);
+ /* search class for a field */
+ fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer);
+ /* search for a method with a specified name and descriptor */
+ methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc);
+ methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *dest);
+ methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+ bool                       class_issubclass(classinfo *sub, classinfo *super);
+ bool                       class_isanysubclass(classinfo *sub, classinfo *super);
+ bool                       class_is_assignable_from(classinfo *to, classinfo *from);
+ bool                       class_is_instance(classinfo *c, java_handle_t *h);
+ classloader_t             *class_get_classloader(classinfo *c);
+ classinfo                 *class_get_superclass(classinfo *c);
+ classinfo                 *class_get_componenttype(classinfo *c);
+ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly);
+ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly);
+ classinfo                 *class_get_declaringclass(classinfo *c);
+ classinfo                 *class_get_enclosingclass(classinfo *c);
+ java_handle_t*             class_get_enclosingconstructor(classinfo *c);
+ methodinfo*                class_get_enclosingmethod_raw(classinfo *c);
+ java_handle_t*             class_get_enclosingmethod(classinfo *c);
+ java_handle_objectarray_t *class_get_interfaces(classinfo *c);
+ java_handle_bytearray_t   *class_get_annotations(classinfo *c);
+ int32_t                    class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib);
+ java_handle_t             *class_get_name(classinfo *c);
+ #if defined(ENABLE_JAVASE)
+ utf                       *class_get_signature(classinfo *c);
+ #endif
+ /* some debugging functions */
+ #if !defined(NDEBUG)
+ void class_printflags(classinfo *c);
+ void class_print(classinfo *c);
+ void class_println(classinfo *c);
+ void class_classref_print(constant_classref *cr);
+ void class_classref_println(constant_classref *cr);
+ void class_classref_or_classinfo_print(classref_or_classinfo c);
+ void class_classref_or_classinfo_println(classref_or_classinfo c);
+ #endif
+ /* debug purposes */
+ void class_showmethods(classinfo *c);
+ void class_showconstantpool(classinfo *c);
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif /* _CLASS_HPP */
+ /*
+  * 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
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  */
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index f1c085114dcf6849332904033e4482f4775d992f,3c3bace7016621d07fa95fe0ddd201a9e4549b13..962e98f4b04efc6773cae37d814ac99e5d683e55
@@@ -160,11 -160,9 +160,12 @@@ int      opt_ThreadStackSiz
  
  /* Debugging options which can be turned off. */
  
+ bool     opt_AlwaysEmitLongBranches       = false;
  int      opt_DebugExceptions              = 0;
  int      opt_DebugFinalizer               = 0;
 +#if defined(ENABLE_JITCACHE)
 +int      opt_DebugJitCache                = 0;
 +#endif
  int      opt_DebugLocalReferences         = 0;
  int      opt_DebugLocks                   = 0;
  int      opt_DebugPackage                 = 0;
@@@ -233,9 -231,9 +234,10 @@@ enum 
  
        /* Debugging options which can be turned off. */
  
+       OPT_AlwaysEmitLongBranches,
        OPT_DebugExceptions,
        OPT_DebugFinalizer,
 +  OPT_DebugJitCache,
        OPT_DebugLocalReferences,
        OPT_DebugLocks,
        OPT_DebugPackage,
@@@ -287,11 -285,9 +289,12 @@@ option_t options_XX[] = 
  
        /* Debugging options which can be turned off. */
  
+       { "AlwaysEmitLongBranches",       OPT_AlwaysEmitLongBranches,       OPT_TYPE_BOOLEAN, "Always emit long-branches." },
        { "DebugExceptions",              OPT_DebugExceptions,              OPT_TYPE_BOOLEAN, "debug exceptions" },
        { "DebugFinalizer",               OPT_DebugFinalizer,               OPT_TYPE_BOOLEAN, "debug finalizer thread" },
 +#if defined (ENABLE_JITCACHE)
 +  { "DebugJitCache",                OPT_DebugJitCache,                OPT_TYPE_BOOLEAN, "debug JIT cache actions" },
 +#endif
        { "DebugLocalReferences",         OPT_DebugLocalReferences,         OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
        { "DebugLocks",                   OPT_DebugLocks,                   OPT_TYPE_BOOLEAN, "print debug information for locks" },
        { "DebugPackage",                 OPT_DebugPackage,                 OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
index 0861d0e6f728bff5c5c8dc4e897483d5b928e4ca,1758add5c3a757ba8858a35ad51f1177f1d29667..460f595dc7a513b3b5f16ce390e558da6e3ba527
@@@ -182,11 -182,9 +182,12 @@@ extern int      opt_ThreadStackSize
  
  /* Debugging options which can be turned off. */
  
+ extern bool     opt_AlwaysEmitLongBranches;
  extern int      opt_DebugExceptions;
  extern int      opt_DebugFinalizer;
 +#if defined(ENABLE_JITCACHE)
 +extern int      opt_DebugJitCache;
 +#endif
  extern int      opt_DebugLocalReferences;
  extern int      opt_DebugLocks;
  extern int      opt_DebugPatcher;
Simple merge
index 0000000000000000000000000000000000000000,1d1173a87d4bca833f37cb6b09aa926f02ea596f..cdd42a733ef852c8ec3cb955bc0695fdcbcf00a5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,3164 +1,3164 @@@
 -              assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+ /* src/vm/resolve.cpp - resolving classes/interfaces/fields/methods
+    Copyright (C) 1996-2005, 2006, 2007, 2008
+    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+    This file is part of CACAO.
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License as
+    published by the Free Software Foundation; either version 2, or (at
+    your option) any later version.
+    This program is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+ */
+ #include "config.h"
+ #include <assert.h>
+ #include "vm/types.h"
+ #include "mm/memory.h"
+ #include "vm/access.h"
+ #include "vm/classcache.h"
+ #include "vm/descriptor.h"
+ #include "vm/exceptions.hpp"
+ #include "vm/global.h"
+ #include "vm/globals.hpp"
+ #include "vm/linker.h"
+ #include "vm/loader.hpp"
+ #include "vm/options.h"
+ #include "vm/primitive.hpp"
+ #include "vm/resolve.hpp"
+ #include "vm/jit/jit.hpp"
+ #include "vm/jit/verify/typeinfo.h"
+ /******************************************************************************/
+ /* DEBUG HELPERS                                                              */
+ /******************************************************************************/
+ /*#define RESOLVE_VERBOSE*/
+ /* resolve_handle_pending_exception ********************************************
+    Convert a pending ClassNotFoundException into a
+    NoClassDefFoundError if requested.
+    See: hotspot/src/share/vm/classfile/systemDictionary.cpp
+    (handle_resolution_exception)
+    ARGUMENTS:
+        classname .... name of the class currently resolved
+        throwError ... if true throw a NoClassDefFoundError instead of
+                       a ClassNotFoundException
+ *******************************************************************************/
+ void resolve_handle_pending_exception(bool throwError)
+ {
+       java_handle_t *e;
+       /* Get the current exception. */
+       e = exceptions_get_exception();
+       if (e != NULL) {
+               if (throwError == true) {
+                       /* Convert ClassNotFoundException to
+                          NoClassDefFoundError. */
+                       if (builtin_instanceof(e, class_java_lang_ClassNotFoundException)) {
+                               /* Clear exception, because we are calling Java code
+                                  again. */
+                               exceptions_clear_exception();
+                               /* create new error */
+                               exceptions_throw_noclassdeffounderror_cause(e);
+                       }
+                       else {
+                               return;
+                       }
+               }
+               else {
+                       /* An exception conversion was not requested.  Simply
+                          return. */
+                       return;
+               }
+       }
+ }
+ /******************************************************************************/
+ /* CLASS RESOLUTION                                                           */
+ /******************************************************************************/
+ /* 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;
+       char      *utf_ptr;
+       int        len;
+       char      *msg;
+       s4         msglen;
+       utf       *u;
+       assert(result);
+       assert(referer);
+       assert(classname);
+       assert(mode == resolveLazy || mode == resolveEager);
+       
+       *result = NULL;
+ #ifdef RESOLVE_VERBOSE
+       printf("resolve_class_from_name(");
+       utf_fprint_printable_ascii(stdout,referer->name);
+       printf(",%p,",(void*)referer->classloader);
+       utf_fprint_printable_ascii(stdout,classname);
+       printf(",%d,%d)\n",(int)checkaccess,(int)link);
+ #endif
+       /* lookup if this class has already been loaded */
+       cls = classcache_lookup(referer->classloader, classname);
+ #ifdef RESOLVE_VERBOSE
+       printf("    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++;
+                                       len -= 2;
+                                       /* FALLTHROUGH */
+                               case '[':
+                                       /* the component type is a reference type */
+                                       /* resolve the component type */
+                                       if (!resolve_class_from_name(referer,refmethod,
+                                                                          utf_new(utf_ptr,len),
+                                                                          mode,checkaccess,link,&cls))
+                                               return false; /* exception */
+                                       if (!cls) {
+                                               assert(mode == resolveLazy);
+                                               return true; /* be lazy */
+                                       }
+                                       /* create the array class */
+                                       cls = class_array_of(cls,false);
+                                       if (!cls)
+                                               return false; /* exception */
+                       }
+               }
+               else {
+                       /* the class has not been loaded, yet */
+                       if (mode == resolveLazy)
+                               return true; /* be lazy */
+               }
+ #ifdef RESOLVE_VERBOSE
+               printf("    loading...\n");
+ #endif
+               /* load the class */
+               if (cls == NULL) {
+                       cls = load_class_from_classloader(classname, referer->classloader);
+                       if (cls == NULL)
+                               return false;
+               }
+       }
+       /* the class is now loaded */
+       assert(cls);
+       assert(cls->state & CLASS_LOADED);
+ #ifdef RESOLVE_VERBOSE
+       printf("    checking access rights...\n");
+ #endif
+       
+       /* check access rights of referer to refered class */
+       if (checkaccess && !access_is_accessible_class(referer,cls)) {
+               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 */
+       }
+       /* link the class if necessary */
+       if (link) {
+               if (!(cls->state & CLASS_LINKED))
+                       if (!link_class(cls))
+                               return false; /* exception */
+               assert(cls->state & CLASS_LINKED);
+       }
+       /* resolution succeeds */
+ #ifdef RESOLVE_VERBOSE
+       printf("    success.\n");
+ #endif
+       *result = cls;
+       return true;
+ }
+ /* 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,checkaccess,link,result);
+ }
+ /* resolve_classref_or_classinfo ***********************************************
+  
+    Resolve a symbolic class reference if necessary
+    NOTE: If given, refmethod->clazz 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)
+        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         *referer;
+       
+       assert(cls.any);
+       assert(mode == resolveEager || mode == resolveLazy);
+       assert(result);
+ #ifdef RESOLVE_VERBOSE
+       printf("resolve_classref_or_classinfo(");
+       utf_fprint_printable_ascii(stdout,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
+       printf(",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
+ #endif
+       *result = NULL;
+       if (IS_CLASSREF(cls)) {
+               /* we must resolve this reference */
+               /* 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->clazz (the caller's class) to resolve   */
+               /* the type of the formal argument.                               */
+               referer = (refmethod) ? refmethod->clazz : cls.ref->referer;
+               if (!resolve_class_from_name(referer, refmethod, cls.ref->name,
+                                                                        mode, checkaccess, link, &c))
+                       goto return_exception;
+       } else {
+               /* cls has already been resolved */
+               c = cls.cls;
+               assert(c->state & CLASS_LOADED);
+       }
+       assert(c || (mode == resolveLazy));
+       if (!c)
+               return true; /* be lazy */
+       
+       assert(c);
+       assert(c->state & CLASS_LOADED);
+       if (link) {
+               if (!(c->state & CLASS_LINKED))
+                       if (!link_class(c))
+                               goto return_exception;
+               assert(c->state & CLASS_LINKED);
+       }
+       /* succeeded */
+       *result = c;
+       return true;
+  return_exception:
+       *result = NULL;
+       return false;
+ }
+ /* 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
+   
+    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 resolves eagerly.
+    
+ *******************************************************************************/
+ bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
+ {
+       classinfo *cls;
+       
+       assert(d);
+       assert(result);
+       *result = NULL;
+ #ifdef RESOLVE_VERBOSE
+       printf("resolve_class_from_typedesc(");
+       descriptor_debug_print_typedesc(stdout,d);
+       printf(",%i,%i)\n",(int)checkaccess,(int)link);
+ #endif
+       if (d->type == TYPE_ADR) {
+               /* a reference type */
+               assert(d->classref);
+               if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
+                                                                                  resolveEager,checkaccess,link,&cls))
+                       return false; /* exception */
+       }
+       else {
+               /* a primitive type */
+               cls = Primitive::get_class_by_type(d->primitivetype);
+               assert(cls->state & CLASS_LOADED);
+               if (!(cls->state & CLASS_LINKED))
+                       if (!link_class(cls))
+                               return false; /* exception */
+       }
+       assert(cls);
+       assert(cls->state & CLASS_LOADED);
+       assert(!link || (cls->state & CLASS_LINKED));
+ #ifdef RESOLVE_VERBOSE
+       printf("    result = ");utf_fprint_printable_ascii(stdout,cls->name);printf("\n");
+ #endif
+       *result = cls;
+       return true;
+ }
+ /******************************************************************************/
+ /* SUBTYPE SET CHECKS                                                         */
+ /******************************************************************************/
+ /* resolve_subtype_check *******************************************************
+  
+    Resolve the given types lazily and perform a subtype check
+   
+    IN:
+        refmethod........the method triggering the resolution
+        subtype..........checked to be a subtype of supertype
+          supertype........the super type to check agaings
+          mode.............mode of resolution:
+                             resolveLazy...only resolve if it does not
+                                           require loading classes
+                             resolveEager..load classes if necessary
+        error............which type of exception to throw if
+                         the test fails. May be:
+                             resolveLinkageError, or
+                             resolveIllegalAccessError
+                                               IMPORTANT: If error==resolveIllegalAccessError,
+                                               then array types are not checked.
+    RETURN VALUE:
+        resolveSucceeded.....the check succeeded
+        resolveDeferred......the check could not be performed due to
+                               unresolved types. (This can only happen for
+                                                       mode == resolveLazy.)
+          resolveFailed........the check failed, an exception has been thrown.
+    
+    NOTE:
+          The types are resolved first, so any
+          exception which may occurr during resolution may
+          be thrown by this function.
+    
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ static resolve_result_t resolve_subtype_check(methodinfo *refmethod,
+                                                                                     classref_or_classinfo subtype,
+                                                                                         classref_or_classinfo supertype,
+                                                                                         resolve_mode_t mode,
+                                                                                         resolve_err_t error)
+ {
+       classinfo        *subclass;
+       typeinfo_t        subti;
+       typecheck_result  r;
+       char             *msg;
+       s4                msglen;
+       utf              *u;
+       assert(refmethod);
+       assert(subtype.any);
+       assert(supertype.any);
+       assert(mode == resolveLazy || mode == resolveEager);
+       assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+       /* resolve the subtype */
+       if (!resolve_classref_or_classinfo(refmethod,subtype,mode,false,true,&subclass)) {
+               /* the subclass could not be resolved. therefore we are sure that  */
+               /* no instances of this subclass will ever exist -> skip this test */
+               /* XXX this assumes that class loading has invariant results (as in JVM spec) */
+               exceptions_clear_exception();
+               return resolveSucceeded;
+       }
+       if (!subclass)
+               return resolveDeferred; /* be lazy */
+       assert(subclass->state & CLASS_LINKED);
+       /* do not check access to protected members of arrays */
+       if (error == resolveIllegalAccessError && subclass->name->text[0] == '[') {
+               return resolveSucceeded;
+       }
+       /* perform the subtype check */
+       typeinfo_init_classinfo(&subti,subclass);
+ check_again:
+       r = typeinfo_is_assignable_to_class(&subti,supertype);
+       if (r == typecheck_FAIL)
+               return resolveFailed; /* failed, exception is already set */
+       if (r == typecheck_MAYBE) {
+               assert(IS_CLASSREF(supertype));
+               if (mode == resolveEager) {
+                       if (!resolve_classref_or_classinfo(refmethod,supertype,
+                                                                                          resolveEager,false,true,
+                                                                                          &supertype.cls))
+                       {
+                               return resolveFailed;
+                       }
+                       assert(supertype.cls);
+                       goto check_again;
+               }
+               return resolveDeferred; /* be lazy */
+       }
+       if (!r) {
+               /* sub class relationship is false */
+ #if defined(RESOLVE_VERBOSE)
+               printf("SUBTYPE CHECK FAILED!\n");
+ #endif
+               msglen =
+                       utf_bytes(subclass->name) +
+                       utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype))
+                       + 200;
+               msg = MNEW(char, msglen);
+               strcpy(msg, (error == resolveIllegalAccessError) ?
+                          "illegal access to protected member (" :
+                          "subtype constraint violated (");
+               utf_cat_classname(msg, subclass->name);
+               strcat(msg, " is not a subclass of ");
+               utf_cat_classname(msg, CLASSREF_OR_CLASSINFO_NAME(supertype));
+               strcat(msg, ")");
+               u = utf_new_char(msg);
+               if (error == resolveIllegalAccessError)
+                       exceptions_throw_illegalaccessexception(u);
+               else
+                       exceptions_throw_linkageerror(msg, NULL);
+               /* ATTENTION: We probably need msg for
+                  exceptions_throw_linkageerror. */
+               MFREE(msg, char, msglen);
+               return resolveFailed; /* exception */
+       }
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_lazy_subtype_checks *************************************************
+  
+    Resolve the types to check lazily and perform subtype checks
+   
+    IN:
+        refmethod........the method triggering the resolution
+        subtinfo.........the typeinfo containing the subtypes
+        supertype........the supertype to test againgst
+          mode.............mode of resolution:
+                             resolveLazy...only resolve if it does not
+                                           require loading classes
+                             resolveEager..load classes if necessary
+        error............which type of exception to throw if
+                         the test fails. May be:
+                             resolveLinkageError, or
+                             resolveIllegalAccessError
+                                               IMPORTANT: If error==resolveIllegalAccessError,
+                                               then array types in the set are skipped.
+    RETURN VALUE:
+        resolveSucceeded.....the check succeeded
+        resolveDeferred......the check could not be performed due to
+                               unresolved types
+          resolveFailed........the check failed, an exception has been thrown.
+    
+    NOTE:
+        The references in the set are resolved first, so any
+        exception which may occurr during resolution may
+        be thrown by this function.
+    
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
+                                                                                                       typeinfo_t *subtinfo,
+                                                                                                       classref_or_classinfo supertype,
+                                                                                                       resolve_err_t error)
+ {
+       int count;
+       int i;
+       resolve_result_t result;
+       assert(refmethod);
+       assert(subtinfo);
+       assert(supertype.any);
+       assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+       /* returnAddresses are illegal here */
+       if (TYPEINFO_IS_PRIMITIVE(*subtinfo)) {
+               exceptions_throw_verifyerror(refmethod,
+                               "Invalid use of returnAddress");
+               return resolveFailed;
+       }
+       /* uninitialized objects are illegal here */
+       if (TYPEINFO_IS_NEWOBJECT(*subtinfo)) {
+               exceptions_throw_verifyerror(refmethod,
+                               "Invalid use of uninitialized object");
+               return resolveFailed;
+       }
+       /* the nulltype is always assignable */
+       if (TYPEINFO_IS_NULLTYPE(*subtinfo))
+               return resolveSucceeded;
+       /* every type is assignable to (BOOTSTRAP)java.lang.Object */
+       if (supertype.cls == class_java_lang_Object
+               || (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
+                       && refmethod->clazz->classloader == NULL))
+       {
+               return resolveSucceeded;
+       }
+       if (subtinfo->merged) {
+               /* for a merged type we have to do a series of checks */
+               count = subtinfo->merged->count;
+               for (i=0; i<count; ++i) {
+                       classref_or_classinfo c = subtinfo->merged->list[i];
+                       if (subtinfo->dimension > 0) {
+                               /* a merge of array types */
+                               /* the merged list contains the possible _element_ types, */
+                               /* so we have to create array types with these elements.  */
+                               if (IS_CLASSREF(c)) {
+                                       c.ref = class_get_classref_multiarray_of(subtinfo->dimension,c.ref);
+                               }
+                               else {
+                                       c.cls = class_multiarray_of(subtinfo->dimension,c.cls,false);
+                               }
+                       }
+                       /* do the subtype check against the type c */
+                       result = resolve_subtype_check(refmethod,c,supertype,resolveLazy,error);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+       }
+       else {
+               /* a single type, this is the common case, hopefully */
+               if (CLASSREF_OR_CLASSINFO_NAME(subtinfo->typeclass)
+                       == CLASSREF_OR_CLASSINFO_NAME(supertype))
+               {
+                       /* the class names are the same */
+                   /* equality is guaranteed by the loading constraints */
+                       return resolveSucceeded;
+               }
+               else {
+                       /* some other type name, try to perform the check lazily */
+                       return resolve_subtype_check(refmethod,
+                                                                                subtinfo->typeclass,supertype,
+                                                                                resolveLazy,
+                                                                                error);
+               }
+       }
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_and_check_subtype_set ***********************************************
+  
+    Resolve the references in the given set and test subtype relationships
+   
+    IN:
+        refmethod........the method triggering the resolution
+        ref..............a set of class/interface references
+                         (may be empty)
+        typeref..........the type to test against the set
+        mode.............mode of resolution:
+                             resolveLazy...only resolve if it does not
+                                           require loading classes
+                             resolveEager..load classes if necessary
+        error............which type of exception to throw if
+                         the test fails. May be:
+                             resolveLinkageError, or
+                             resolveIllegalAccessError
+                                               IMPORTANT: If error==resolveIllegalAccessError,
+                                               then array types in the set are skipped.
+    RETURN VALUE:
+        resolveSucceeded.....the check succeeded
+        resolveDeferred......the check could not be performed due to
+                               unresolved types. (This can only happen if
+                                                       mode == resolveLazy.)
+          resolveFailed........the check failed, an exception has been thrown.
+    
+    NOTE:
+        The references in the set are resolved first, so any
+        exception which may occurr during resolution may
+        be thrown by this function.
+    
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ static resolve_result_t resolve_and_check_subtype_set(methodinfo *refmethod,
+                                                                         unresolved_subtype_set *ref,
+                                                                         classref_or_classinfo typeref,
+                                                                         resolve_mode_t mode,
+                                                                         resolve_err_t error)
+ {
+       classref_or_classinfo *setp;
+       resolve_result_t checkresult;
+       assert(refmethod);
+       assert(ref);
+       assert(typeref.any);
+       assert(mode == resolveLazy || mode == resolveEager);
+       assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+ #if defined(RESOLVE_VERBOSE)
+       printf("resolve_and_check_subtype_set:\n");
+       unresolved_subtype_set_debug_dump(ref, stdout);
+       if (IS_CLASSREF(typeref))
+               class_classref_println(typeref.ref);
+       else
+               class_println(typeref.cls);
+ #endif
+       setp = ref->subtyperefs;
+       /* an empty set of tests always succeeds */
+       if (!setp || !setp->any) {
+               return resolveSucceeded;
+       }
+       /* first resolve the type if necessary */
+       if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&(typeref.cls)))
+               return resolveFailed; /* exception */
+       if (!typeref.cls)
+               return resolveDeferred; /* be lazy */
+       assert(typeref.cls->state & CLASS_LINKED);
+       /* iterate over the set members */
+       for (; setp->any; ++setp) {
+               checkresult = resolve_subtype_check(refmethod,*setp,typeref,mode,error);
+ #if defined(RESOLVE_VERBOSE)
+               if (checkresult != resolveSucceeded)
+                       printf("SUBTYPE CHECK FAILED!\n");
+ #endif
+               if (checkresult != resolveSucceeded)
+                       return checkresult;
+       }
+       /* check succeeds */
+       return resolveSucceeded;
+ }
+ #endif /* defined(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;
+       resolve_result_t checkresult;
+       
+       assert(ref);
+       assert(result);
+       assert(mode == resolveLazy || mode == resolveEager);
+       *result = NULL;
+ #ifdef RESOLVE_VERBOSE
+       unresolved_class_debug_dump(ref,stdout);
+ #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->state & CLASS_LOADED) && (cls->state & CLASS_LINKED));
+       /* now we check the subtype constraints */
+       
+       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                                                          &(ref->subtypeconstraints),
+                                                                          CLASSREF_OR_CLASSINFO(cls),
+                                                                          mode,
+                                                                          resolveLinkageError);
+       if (checkresult != resolveSucceeded)
+               return (bool) checkresult;
+       /* 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) {
+               exceptions_throw_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 */
+ /* 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                                                           */
+ /******************************************************************************/
+ /* resolve_field_verifier_checks *******************************************
+  
+    Do the verifier checks necessary after field has been resolved.
+   
+    IN:
+        refmethod........the method containing the reference
+          fieldref.........the field reference
+          container........the class where the field was found
+          fi...............the fieldinfo of the resolved field
+          instanceti.......instance typeinfo, if available
+          valueti..........value typeinfo, if available
+          isstatic.........true if this is a *STATIC* instruction
+          isput............true if this is a PUT* instruction
+   
+    RETURN VALUE:
+        resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+        resolveFailed.......exception has been thrown
+    
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
+                                                                                          constant_FMIref *fieldref,
+                                                                                          classinfo *container,
+                                                                                          fieldinfo *fi,
+                                                                                          typeinfo_t *instanceti,
+                                                                                          typeinfo_t *valueti,
+                                                                                          bool isstatic,
+                                                                                          bool isput)
+ {
+       classinfo         *declarer;
+       classinfo         *referer;
+       resolve_result_t   result;
+       constant_classref *fieldtyperef;
+       char              *msg;
+       s4                 msglen;
+       utf               *u;
+       assert(refmethod);
+       assert(fieldref);
+       assert(container);
+       assert(fi);
+       /* get the classinfos and the field type */
+       referer = refmethod->clazz;
+       assert(referer);
+       declarer = fi->clazz;
+       assert(declarer);
+       assert(referer->state & CLASS_LINKED);
+       fieldtyperef = fieldref->parseddesc.fd->classref;
+       /* check static */
+ #if true != 1
+ #error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
+ #endif
+       if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
+               /* a static field is accessed via an instance, or vice versa */
+               exceptions_throw_incompatibleclasschangeerror(declarer,
+                                                                                                         (fi->flags & ACC_STATIC)
+                                                                                                         ? "static field accessed via instance"
+                                                                                                         : "instance field  accessed without instance");
+               return resolveFailed;
+       }
+       /* check access rights */
+       if (!access_is_accessible_member(referer,declarer,fi->flags)) {
+               msglen =
+                       utf_bytes(declarer->name) +
+                       utf_bytes(fi->name) +
+                       utf_bytes(referer->name) +
+                       100;
+               msg = MNEW(char, msglen);
+               strcpy(msg, "field is not accessible (");
+               utf_cat_classname(msg, declarer->name);
+               strcat(msg, ".");
+               utf_cat(msg, fi->name);
+               strcat(msg, " from ");
+               utf_cat_classname(msg, referer->name);
+               strcat(msg, ")");
+               u = utf_new_char(msg);
+               MFREE(msg, char, msglen);
+               exceptions_throw_illegalaccessexception(u);
+               return resolveFailed; /* exception */
+       }
+       /* for non-static methods we have to check the constraints on the         */
+       /* instance type                                                          */
+       if (instanceti) {
+               typeinfo_t *insttip;
+               typeinfo_t tinfo;
+               /* The instanceslot must contain a reference to a non-array type */
+               if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
+                       return resolveFailed;
+               }
+               if (TYPEINFO_IS_ARRAY(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
+                       return resolveFailed;
+               }
+               if (isput && TYPEINFO_IS_NEWOBJECT(*instanceti))
+               {
+                       /* The instruction writes a field in an uninitialized object. */
+                       /* This is only allowed when a field of an uninitialized 'this' object is */
+                       /* written inside an initialization method                                */
+                       classinfo *initclass;
+                       instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+                       if (ins != NULL) {
+                               exceptions_throw_verifyerror(refmethod, "accessing field of uninitialized object");
+                               return resolveFailed;
+                       }
+                       /* XXX check that class of field == refmethod->clazz */
+                       initclass = referer; /* XXX classrefs */
+                       assert(initclass->state & CLASS_LINKED);
+                       typeinfo_init_classinfo(&tinfo, initclass);
+                       insttip = &tinfo;
+               }
+               else {
+                       insttip = instanceti;
+               }
+               result = resolve_lazy_subtype_checks(refmethod,
+                               insttip,
+                               CLASSREF_OR_CLASSINFO(container),
+                               resolveLinkageError);
+               if (result != resolveSucceeded)
+                       return result;
+               /* check protected access */
+               if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
+               {
+                       result = resolve_lazy_subtype_checks(refmethod,
+                                       instanceti,
+                                       CLASSREF_OR_CLASSINFO(referer),
+                                       resolveIllegalAccessError);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+       }
+       /* for PUT* instructions we have to check the constraints on the value type */
+       if (valueti) {
+               assert(fieldtyperef);
+               /* check subtype constraints */
+               result = resolve_lazy_subtype_checks(refmethod,
+                               valueti,
+                               CLASSREF_OR_CLASSINFO(fieldtyperef),
+                               resolveLinkageError);
+               if (result != resolveSucceeded)
+                       return result;
+       }
+       /* impose loading constraint on field type */
+       if (fi->type == TYPE_ADR) {
+               assert(fieldtyperef);
+               if (!classcache_add_constraint(declarer->classloader,
+                                                                          referer->classloader,
+                                                                          fieldtyperef->name))
+                       return resolveFailed;
+       }
+       /* XXX impose loading constraint on instance? */
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_field_lazy **********************************************************
+  
+    Resolve an unresolved field reference lazily
+    NOTE: This function does NOT do any verification checks. In case of a
+          successful resolution, you must call resolve_field_verifier_checks
+                in order to perform the necessary checks!
+   
+    IN:
+          refmethod........the referer method
+          fieldref.........the field reference
+   
+    RETURN VALUE:
+        resolveSucceeded.....the reference has been resolved
+        resolveDeferred......the resolving could not be performed lazily
+          resolveFailed........resolving failed, an exception has been thrown.
+    
+ *******************************************************************************/
+ resolve_result_t resolve_field_lazy(methodinfo *refmethod,
+                                                                       constant_FMIref *fieldref)
+ {
+       classinfo *referer;
+       classinfo *container;
+       fieldinfo *fi;
+       assert(refmethod);
+       /* the class containing the reference */
+       referer = refmethod->clazz;
+       assert(referer);
+       /* check if the field itself is already resolved */
+       if (IS_FMIREF_RESOLVED(fieldref))
+               return resolveSucceeded;
+       /* first we must resolve the class containg the field */
+       /* XXX can/may lazyResolving trigger linking? */
+       if (!resolve_class_from_name(referer, refmethod,
+                  fieldref->p.classref->name, resolveLazy, true, true, &container))
+       {
+               /* the class reference could not be resolved */
+               return resolveFailed; /* exception */
+       }
+       if (!container)
+               return resolveDeferred; /* be lazy */
+       assert(container->state & CLASS_LINKED);
+       /* now we must find the declaration of the field in `container`
+        * or one of its superclasses */
+       fi = class_resolvefield(container,
+                                                       fieldref->name, fieldref->descriptor,
+                                                       referer);
+       if (!fi) {
+               /* The field does not exist. But since we were called lazily, */
+               /* this error must not be reported now. (It will be reported   */
+               /* if eager resolving of this field is ever tried.)           */
+               exceptions_clear_exception();
+               return resolveDeferred; /* be lazy */
+       }
+       /* cache the result of the resolution */
+       fieldref->p.field = fi;
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ /* resolve_field ***************************************************************
+  
+    Resolve an unresolved field reference
+   
+    IN:
+        ref..............struct containing the reference
+        mode.............mode of resolution:
+                             resolveLazy...only resolve if it does not
+                                           require loading classes
+                             resolveEager..load classes if necessary
+   
+    OUT:
+        *result..........set to the result of resolution, or to NULL if
+                         the reference has not been resolved
+                         In the case of an exception, *result is
+                         guaranteed to be set to NULL.
+   
+    RETURN VALUE:
+        true.............everything ok 
+                         (*result may still be NULL for resolveLazy)
+        false............an exception has been thrown
+    
+ *******************************************************************************/
+ bool resolve_field(unresolved_field *ref,
+                                  resolve_mode_t mode,
+                                  fieldinfo **result)
+ {
+       classinfo *referer;
+       classinfo *container;
+       classinfo *declarer;
+       constant_classref *fieldtyperef;
+       fieldinfo *fi;
+       resolve_result_t checkresult;
+       assert(ref);
+       assert(result);
+       assert(mode == resolveLazy || mode == resolveEager);
+       *result = NULL;
+ #ifdef RESOLVE_VERBOSE
+       unresolved_field_debug_dump(ref,stdout);
+ #endif
+       /* the class containing the reference */
+       referer = ref->referermethod->clazz;
+       assert(referer);
+       /* check if the field itself is already resolved */
+       if (IS_FMIREF_RESOLVED(ref->fieldref)) {
+               fi = ref->fieldref->p.field;
+               container = fi->clazz;
+               goto resolved_the_field;
+       }
+       /* first we must resolve the class containg the field */
+       if (!resolve_class_from_name(referer,ref->referermethod,
+                                          ref->fieldref->p.classref->name,mode,true,true,&container))
+       {
+               /* the class reference could not be resolved */
+               return false; /* exception */
+       }
+       if (!container)
+               return true; /* be lazy */
+       assert(container);
+       assert(container->state & CLASS_LOADED);
+       assert(container->state & CLASS_LINKED);
+       /* now we must find the declaration of the field in `container`
+        * or one of its superclasses */
+ #ifdef RESOLVE_VERBOSE
+               printf("    resolving field in class...\n");
+ #endif
+       fi = class_resolvefield(container,
+                                                       ref->fieldref->name,ref->fieldref->descriptor,
+                                                       referer);
+       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.)           */
+                       exceptions_clear_exception();
+                       return true; /* be lazy */
+               }
+               return false; /* exception */
+       }
+       /* cache the result of the resolution */
+       ref->fieldref->p.field = fi;
+ resolved_the_field:
+ #ifdef ENABLE_VERIFIER
+       /* Checking opt_verify is ok here, because the NULL iptr guarantees */
+       /* that no missing parts of an instruction will be accessed.        */
+       if (opt_verify) {
+               checkresult = resolve_field_verifier_checks(
+                               ref->referermethod,
+                               ref->fieldref,
+                               container,
+                               fi,
+                               NULL, /* instanceti, handled by constraints below */
+                               NULL, /* valueti, handled by constraints below  */
+                               (ref->flags & RESOLVE_STATIC) != 0, /* isstatic */
+                               (ref->flags & RESOLVE_PUTFIELD) != 0 /* isput */);
+               if (checkresult != resolveSucceeded)
+                       return (bool) checkresult;
+               declarer = fi->clazz;
+               assert(declarer);
+               assert(declarer->state & CLASS_LOADED);
+               assert(declarer->state & CLASS_LINKED);
+               /* for non-static accesses we have to check the constraints on the */
+               /* instance type */
+               if (!(ref->flags & RESOLVE_STATIC)) {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(container),
+                                       mode, resolveLinkageError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
+               }
+               fieldtyperef = ref->fieldref->parseddesc.fd->classref;
+               /* for PUT* instructions we have to check the constraints on the value type */
+               if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
+                       assert(fieldtyperef);
+                       if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
+                               /* check subtype constraints */
+                               checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                               &(ref->valueconstraints),
+                                               CLASSREF_OR_CLASSINFO(fieldtyperef),
+                                               mode, resolveLinkageError);
+                               if (checkresult != resolveSucceeded)
+                                       return (bool) checkresult;
+                       }
+               }
+               /* check protected access */
+               if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(referer),
+                                       mode,
+                                       resolveIllegalAccessError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
+               }
+       }
+ #endif /* ENABLE_VERIFIER */
+       /* succeed */
+       *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                                                          */
+ /******************************************************************************/
+ /* resolve_method_invokespecial_lookup *****************************************
+  
+    Do the special lookup for methods invoked by INVOKESPECIAL
+   
+    IN:
+        refmethod........the method containing the reference
+          mi...............the methodinfo of the resolved method
+   
+    RETURN VALUE:
+        a methodinfo *...the result of the lookup,
+          NULL.............an exception has been thrown
+    
+ *******************************************************************************/
+ methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
+                                                                                                methodinfo *mi)
+ {
+       classinfo *declarer;
+       classinfo *referer;
+       assert(refmethod);
+       assert(mi);
+       /* get referer and declarer classes */
+       referer = refmethod->clazz;
+       assert(referer);
+       declarer = mi->clazz;
+       assert(declarer);
+       assert(referer->state & CLASS_LINKED);
+       /* checks for INVOKESPECIAL:                                       */
+       /* for <init> and methods of the current class we don't need any   */
+       /* special checks. Otherwise we must verify that the called method */
+       /* belongs to a super class of the current class                   */
+       if ((referer != declarer) && (mi->name != utf_init)) {
+               /* check that declarer is a super class of the current class   */
+               if (!class_issubclass(referer,declarer)) {
+                       exceptions_throw_verifyerror(refmethod,
+                                       "INVOKESPECIAL calling non-super class method");
+                       return NULL;
+               }
+               /* if the referer has ACC_SUPER set, we must do the special    */
+               /* lookup starting with the direct super class of referer      */
+               if ((referer->flags & ACC_SUPER) != 0) {
+                       mi = class_resolvemethod(referer->super,
+                                                                        mi->name,
+                                                                        mi->descriptor);
+                       if (mi == NULL) {
+                               /* the spec calls for an AbstractMethodError in this case */
+                               exceptions_throw_abstractmethoderror();
+                               return NULL;
+                       }
+               }
+       }
+       /* everything ok */
+       return mi;
+ }
+ /* resolve_method_verifier_checks ******************************************
+  
+    Do the verifier checks necessary after a method has been resolved.
+   
+    IN:
+        refmethod........the method containing the reference
+          methodref........the method reference
+          mi...............the methodinfo of the resolved method
+          invokestatic.....true if the method is invoked by INVOKESTATIC
+   
+    RETURN VALUE:
+        resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+        resolveFailed.......exception has been thrown
+    
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
+                                                                                               constant_FMIref *methodref,
+                                                                                               methodinfo *mi,
+                                                                                               bool invokestatic)
+ {
+       classinfo *declarer;
+       classinfo *referer;
+       char      *msg;
+       s4         msglen;
+       utf       *u;
+       assert(refmethod);
+       assert(methodref);
+       assert(mi);
+ #ifdef RESOLVE_VERBOSE
+       printf("resolve_method_verifier_checks\n");
+       printf("    flags: %02x\n",mi->flags);
+ #endif
+       /* get the classinfos and the method descriptor */
+       referer = refmethod->clazz;
+       assert(referer);
+       declarer = mi->clazz;
+       assert(declarer);
+       /* check static */
+       if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
+               /* a static method is accessed via an instance, or vice versa */
+               exceptions_throw_incompatibleclasschangeerror(declarer,
+                                                                                                         (mi->flags & ACC_STATIC)
+                                                                                                         ? "static method called via instance"
+                                                                                                         : "instance method called without instance");
+               return resolveFailed;
+       }
+       /* check access rights */
+       if (!access_is_accessible_member(referer,declarer,mi->flags)) {
+               /* XXX clean this up. this should be in exceptions.c */
+               msglen =
+                       utf_bytes(declarer->name) +
+                       utf_bytes(mi->name) +
+                       utf_bytes(mi->descriptor) +
+                       utf_bytes(referer->name) +
+                       100;
+               msg = MNEW(char, msglen);
+               strcpy(msg, "method is not accessible (");
+               utf_cat_classname(msg, declarer->name);
+               strcat(msg, ".");
+               utf_cat(msg, mi->name);
+               utf_cat(msg, mi->descriptor);
+               strcat(msg, " from ");
+               utf_cat_classname(msg, referer->name);
+               strcat(msg, ")");
+               u = utf_new_char(msg);
+               MFREE(msg, char, msglen);
+               exceptions_throw_illegalaccessexception(u);
+               return resolveFailed; /* exception */
+       }
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_method_instance_type_checks *****************************************
+    Check the instance type of a method invocation.
+    IN:
+        refmethod........the method containing the reference
+          mi...............the methodinfo of the resolved method
+          instanceti.......typeinfo of the instance slot
+          invokespecial....true if the method is invoked by INVOKESPECIAL
+    RETURN VALUE:
+        resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+        resolveFailed.......exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
+                                                                                                        methodinfo *mi,
+                                                                                                        typeinfo_t *instanceti,
+                                                                                                        bool invokespecial)
+ {
+       typeinfo_t         tinfo;
+       typeinfo_t        *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->clazz);
+               tip = &tinfo;
+               if (!typeinfo_init_class(tip, initclass))
+                       return resolveFailed;
+       }
+       else {
+               tip = instanceti;
+       }
+       result = resolve_lazy_subtype_checks(refmethod,
+                                                                                tip,
+                                                                                CLASSREF_OR_CLASSINFO(mi->clazz),
+                                                                                resolveLinkageError);
+       if (result != resolveSucceeded)
+               return result;
+       /* check protected access */
+       /* XXX use other `declarer` than mi->clazz? */
+       if (((mi->flags & ACC_PROTECTED) != 0)
+                       && !SAME_PACKAGE(mi->clazz, refmethod->clazz))
+       {
+               result = resolve_lazy_subtype_checks(refmethod,
+                               tip,
+                               CLASSREF_OR_CLASSINFO(refmethod->clazz),
+                               resolveIllegalAccessError);
+               if (result != resolveSucceeded)
+                       return result;
+       }
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_method_param_type_checks ********************************************
+    Check non-instance parameter types of a method invocation.
+    IN:
+          jd...............jitdata of the method doing the call
+        refmethod........the method containing the reference
+          iptr.............the invoke instruction
+          mi...............the methodinfo of the resolved method
+          invokestatic.....true if the method is invoked by INVOKESTATIC
+    RETURN VALUE:
+        resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+        resolveFailed.......exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ resolve_result_t resolve_method_param_type_checks(jitdata *jd, 
+                                                                                                 methodinfo *refmethod,
+                                                                                                 instruction *iptr, 
+                                                                                                 methodinfo *mi,
+                                                                                                 bool invokestatic)
+ {
+       varinfo         *param;
+       resolve_result_t result;
+       methoddesc      *md;
+       typedesc        *paramtypes;
+       s4               type;
+       s4               instancecount;
+       s4               i;
+       assert(jd);
+       instancecount = (invokestatic) ? 0 : 1;
+       /* check subtype constraints for TYPE_ADR parameters */
+       md = mi->parseddesc;
+       paramtypes = md->paramtypes;
+       for (i = md->paramcount-1-instancecount; i>=0; --i) {
+               param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+               type = md->paramtypes[i+instancecount].type;
+               assert(param);
+               assert(type == param->type);
+               if (type == TYPE_ADR) {
+                       result = resolve_lazy_subtype_checks(refmethod,
+                                       &(param->typeinfo),
+                                       CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
+                                       resolveLinkageError);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+       }
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_method_param_type_checks_stackbased *********************************
+    Check non-instance parameter types of a method invocation.
+    IN:
+        refmethod........the method containing the reference
+          mi...............the methodinfo of the resolved method
+          invokestatic.....true if the method is invoked by INVOKESTATIC
+          stack............TOS before the INVOKE instruction
+    RETURN VALUE:
+        resolveSucceeded....everything ok
+          resolveDeferred.....tests could not be done, have been deferred
+        resolveFailed.......exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ resolve_result_t resolve_method_param_type_checks_stackbased(
+               methodinfo *refmethod, 
+               methodinfo *mi,
+               bool invokestatic, 
+               typedescriptor_t *stack)
+ {
+       typedescriptor_t  *param;
+       resolve_result_t result;
+       methoddesc      *md;
+       typedesc        *paramtypes;
+       s4               type;
+       s4               instancecount;
+       s4               i;
+       instancecount = (invokestatic) ? 0 : 1;
+       /* check subtype constraints for TYPE_ADR parameters */
+       md = mi->parseddesc;
+       paramtypes = md->paramtypes;
+       param = stack - (md->paramslots - 1 - instancecount);
+       for (i = instancecount; i < md->paramcount; ++i) {
+               type = md->paramtypes[i].type;
+               assert(type == param->type);
+               if (type == TYPE_ADR) {
+                       result = resolve_lazy_subtype_checks(refmethod,
+                                       &(param->typeinfo),
+                                       CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
+                                       resolveLinkageError);
+                       if (result != resolveSucceeded)
+                               return result;
+               }
+               param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
+       }
+       /* everything ok */
+       return resolveSucceeded;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_method_loading_constraints ******************************************
+    Impose loading constraints on the parameters and return type of the
+    given method.
+    IN:
+        referer..........the class refering to the method
+          mi...............the method
+    RETURN VALUE:
+        true................everything ok
+          false...............an exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ bool resolve_method_loading_constraints(classinfo *referer,
+                                                                               methodinfo *mi)
+ {
+       methoddesc *md;
+       typedesc   *paramtypes;
+       utf        *name;
+       s4          i;
+       s4          instancecount;
+       /* impose loading constraints on parameters (including instance) */
+       md = mi->parseddesc;
+       paramtypes = md->paramtypes;
+       instancecount = (mi->flags & ACC_STATIC) / ACC_STATIC;
+       for (i = 0; i < md->paramcount; i++) {
+               if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
+                       if (i < instancecount) {
+                               /* The type of the 'this' pointer is the class containing */
+                               /* the method definition. Since container is the same as, */
+                               /* or a subclass of declarer, we also constrain declarer  */
+                               /* by transitivity of loading constraints.                */
+                               name = mi->clazz->name;
+                       }
+                       else {
+                               name = paramtypes[i].classref->name;
+                       }
+                       /* The caller (referer) and the callee (container) must agree */
+                       /* on the types of the parameters.                            */
+                       if (!classcache_add_constraint(referer->classloader,
+                                                                                  mi->clazz->classloader, name))
+                               return false; /* exception */
+               }
+       }
+       /* impose loading constraint onto return type */
+       if (md->returntype.type == TYPE_ADR) {
+               /* The caller (referer) and the callee (container) must agree */
+               /* on the return type.                                        */
+               if (!classcache_add_constraint(referer->classloader,
+                                       mi->clazz->classloader,
+                                       md->returntype.classref->name))
+                       return false; /* exception */
+       }
+       /* everything ok */
+       return true;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_method_lazy *********************************************************
+  
+    Resolve an unresolved method reference lazily
+   
+    NOTE: This function does NOT do any verification checks. In case of a
+          successful resolution, you must call resolve_method_verifier_checks
+                in order to perform the necessary checks!
+   
+    IN:
+          refmethod........the referer method
+          methodref........the method reference
+          invokespecial....true if this is an INVOKESPECIAL instruction
+   
+    RETURN VALUE:
+        resolveSucceeded.....the reference has been resolved
+        resolveDeferred......the resolving could not be performed lazily
+          resolveFailed........resolving failed, an exception has been thrown.
+    
+ *******************************************************************************/
+ resolve_result_t resolve_method_lazy(methodinfo *refmethod,
+                                                                        constant_FMIref *methodref,
+                                                                        bool invokespecial)
+ {
+       classinfo *referer;
+       classinfo *container;
+       methodinfo *mi;
+       assert(refmethod);
+ #ifdef RESOLVE_VERBOSE
+       printf("resolve_method_lazy\n");
+ #endif
+       /* the class containing the reference */
+       referer = refmethod->clazz;
+       assert(referer);
+       /* check if the method itself is already resolved */
+       if (IS_FMIREF_RESOLVED(methodref))
+               return resolveSucceeded;
+       /* first we must resolve the class containg the method */
+       if (!resolve_class_from_name(referer, refmethod,
+                  methodref->p.classref->name, resolveLazy, true, true, &container))
+       {
+               /* the class reference could not be resolved */
+               return resolveFailed; /* exception */
+       }
+       if (!container)
+               return resolveDeferred; /* be lazy */
+       assert(container->state & CLASS_LINKED);
+       /* now we must find the declaration of the method in `container`
+        * or one of its superclasses */
+       if (container->flags & ACC_INTERFACE) {
+               mi = class_resolveinterfacemethod(container,
+                                                                             methodref->name,
+                                                                                 methodref->descriptor,
+                                                                             referer, true);
+       } else {
+               mi = class_resolveclassmethod(container,
+                                                                         methodref->name,
+                                                                         methodref->descriptor,
+                                                                         referer, true);
+       }
+       if (!mi) {
+               /* The method does not exist. But since we were called lazily, */
+               /* this error must not be reported now. (It will be reported   */
+               /* if eager resolving of this method is ever tried.)           */
+               exceptions_clear_exception();
+               return resolveDeferred; /* be lazy */
+       }
+       if (invokespecial) {
+               mi = resolve_method_invokespecial_lookup(refmethod, mi);
+               if (!mi)
+                       return resolveFailed; /* exception */
+       }
+       /* have the method params already been parsed? no, do it. */
+       if (!mi->parseddesc->params)
+               if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
+                       return resolveFailed;
+       /* cache the result of the resolution */
+       methodref->p.method = mi;
+       /* succeed */
+       return resolveSucceeded;
+ }
+ /* 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;
+       classinfo *declarer;
+       methodinfo *mi;
+       typedesc *paramtypes;
+       int instancecount;
+       int i;
+       resolve_result_t checkresult;
+       assert(ref);
+       assert(result);
+       assert(mode == resolveLazy || mode == resolveEager);
+ #ifdef RESOLVE_VERBOSE
+       unresolved_method_debug_dump(ref,stdout);
+ #endif
+       *result = NULL;
+       /* the class containing the reference */
+       referer = ref->referermethod->clazz;
+       assert(referer);
+       /* check if the method itself is already resolved */
+       if (IS_FMIREF_RESOLVED(ref->methodref)) {
+               mi = ref->methodref->p.method;
+               container = mi->clazz;
+               goto resolved_the_method;
+       }
+       /* first we must resolve the class containing the method */
+       if (!resolve_class_from_name(referer,ref->referermethod,
+                                          ref->methodref->p.classref->name,mode,true,true,&container))
+       {
+               /* the class reference could not be resolved */
+               return false; /* exception */
+       }
+       if (!container)
+               return true; /* be lazy */
+       assert(container);
+       assert(container->state & CLASS_LINKED);
+       /* now we must find the declaration of the method in `container`
+        * or one of its superclasses */
+       if (container->flags & ACC_INTERFACE) {
+               mi = class_resolveinterfacemethod(container,
+                                                                             ref->methodref->name,
+                                                                                 ref->methodref->descriptor,
+                                                                             referer, true);
+       } else {
+               mi = class_resolveclassmethod(container,
+                                                                         ref->methodref->name,
+                                                                         ref->methodref->descriptor,
+                                                                         referer, true);
+       }
+       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.)           */
+                       exceptions_clear_exception();
+                       return true; /* be lazy */
+               }
+               return false; /* exception */ /* XXX set exceptionptr? */
+       }
+       /* { the method reference has been resolved } */
+       if (ref->flags & RESOLVE_SPECIAL) {
+               mi = resolve_method_invokespecial_lookup(ref->referermethod,mi);
+               if (!mi)
+                       return false; /* exception */
+       }
+       /* have the method params already been parsed? no, do it. */
+       if (!mi->parseddesc->params)
+               if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
+                       return false;
+       /* cache the resolution */
+       ref->methodref->p.method = mi;
+ resolved_the_method:
+ #ifdef ENABLE_VERIFIER
+       if (opt_verify) {
+               checkresult = resolve_method_verifier_checks(
+                               ref->referermethod,
+                               ref->methodref,
+                               mi,
+                               (ref->flags & RESOLVE_STATIC));
+               if (checkresult != resolveSucceeded)
+                       return (bool) checkresult;
+               /* impose loading constraints on params and return type */
+               if (!resolve_method_loading_constraints(referer, mi))
+                       return false;
+               declarer = mi->clazz;
+               assert(declarer);
+               assert(referer->state & CLASS_LINKED);
+               /* for non-static methods we have to check the constraints on the         */
+               /* instance type                                                          */
+               if (!(ref->flags & RESOLVE_STATIC)) {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(container),
+                                       mode,
+                                       resolveLinkageError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
+                       instancecount = 1;
+               }
+               else {
+                       instancecount = 0;
+               }
+               /* check subtype constraints for TYPE_ADR parameters */
++              assert(mi == ref->methodref->p.method || mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+               paramtypes = mi->parseddesc->paramtypes;
+               for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
+                       if (paramtypes[i+instancecount].type == TYPE_ADR) {
+                               if (ref->paramconstraints) {
+                                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                                       ref->paramconstraints + i,
+                                                       CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
+                                                       mode,
+                                                       resolveLinkageError);
+                                       if (checkresult != resolveSucceeded)
+                                               return (bool) checkresult;
+                               }
+                       }
+               }
+               /* check protected access */
+               if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
+               {
+                       checkresult = resolve_and_check_subtype_set(ref->referermethod,
+                                       &(ref->instancetypes),
+                                       CLASSREF_OR_CLASSINFO(referer),
+                                       mode,
+                                       resolveIllegalAccessError);
+                       if (checkresult != resolveSucceeded)
+                               return (bool) checkresult;
+               }
+       }
+ #endif /* ENABLE_VERIFIER */
+       /* succeed */
+       *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                                               */
+ /******************************************************************************/
+ #ifdef ENABLE_VERIFIER
+ static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
+                                                                                                methodinfo *refmethod,
+                                                                                                unresolved_subtype_set *stset,
+                                                                                                typeinfo_t *tinfo,
+                                                                                                utf *declaredclassname)
+ {
+       int count;
+       int i;
+       assert(stset);
+       assert(tinfo);
+ #ifdef RESOLVE_VERBOSE
+       printf("unresolved_subtype_set_from_typeinfo\n");
+ #ifdef TYPEINFO_DEBUG
+       typeinfo_print(stdout,tinfo,4);
+ #endif
+       printf("    declared classname:");utf_fprint_printable_ascii(stdout,declaredclassname);
+       printf("\n");
+ #endif
+       if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
+               exceptions_throw_verifyerror(refmethod,
+                               "Invalid use of returnAddress");
+               return false;
+       }
+       if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
+               exceptions_throw_verifyerror(refmethod,
+                               "Invalid use of uninitialized object");
+               return false;
+       }
+       /* the nulltype is always assignable */
+       if (TYPEINFO_IS_NULLTYPE(*tinfo))
+               goto empty_set;
+       /* every type is assignable to (BOOTSTRAP)java.lang.Object */
+       if (declaredclassname == utf_java_lang_Object
+                       && referer->classloader == NULL) /* XXX do loading constraints make the second check obsolete? */
+       {
+               goto empty_set;
+       }
+       if (tinfo->merged) {
+               count = tinfo->merged->count;
+               stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
+               for (i=0; i<count; ++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 */
+       }
+       else {
+               if ((IS_CLASSREF(tinfo->typeclass)
+                                       ? tinfo->typeclass.ref->name
+                                       : tinfo->typeclass.cls->name) == declaredclassname)
+               {
+                       /* the class names are the same */
+                   /* equality is guaranteed by the loading constraints */
+                       goto empty_set;
+               }
+               else {
+                       stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
+                       stset->subtyperefs[0] = tinfo->typeclass;
+                       stset->subtyperefs[1].any = NULL; /* terminate */
+               }
+       }
+       return true;
+ 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_t *valuetype)
+ {
+       unresolved_class *ref;
+ #ifdef RESOLVE_VERBOSE
+       printf("create_unresolved_class\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,classref->referer->name);fputc('\n',stdout);
+       if (refmethod) {
+               printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+               printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+       }
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,classref->name);fputc('\n',stdout);
+ #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->name))
+                       return NULL;
+       }
+       else {
+               UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
+       }
+       return ref;
+ }
+ #endif /* ENABLE_VERIFIER */
+ /* resolve_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 * resolve_create_unresolved_field(classinfo *referer,
+                                                                                                  methodinfo *refmethod,
+                                                                                                  instruction *iptr)
+ {
+       unresolved_field *ref;
+       constant_FMIref *fieldref = NULL;
+ #ifdef RESOLVE_VERBOSE
+       printf("create_unresolved_field\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+       printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+       printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+ #endif
+       ref = NEW(unresolved_field);
+       ref->flags = 0;
+       ref->referermethod = refmethod;
+       UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
+       switch (iptr->opc) {
+               case ICMD_PUTFIELD:
+                       ref->flags |= RESOLVE_PUTFIELD;
+                       break;
+               case ICMD_PUTFIELDCONST:
+                       ref->flags |= RESOLVE_PUTFIELD;
+                       break;
+               case ICMD_PUTSTATIC:
+                       ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
+                       break;
+               case ICMD_PUTSTATICCONST:
+                       ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
+                       break;
+               case ICMD_GETFIELD:
+                       break;
+               case ICMD_GETSTATIC:
+                       ref->flags |= RESOLVE_STATIC;
+                       break;
+ #if !defined(NDEBUG)
+               default:
+                       assert(false);
+ #endif
+       }
+       fieldref = iptr->sx.s23.s3.fmiref;
+       assert(fieldref);
+ #ifdef RESOLVE_VERBOSE
+ /*    printf("    class  : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout);*/
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+       printf("    desc   : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
+       printf("    type   : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
+       fputc('\n',stdout);
+ #endif
+       ref->fieldref = fieldref;
+       return ref;
+ }
+ /* resolve_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)
+          instanceti.......instance typeinfo, if available
+          valueti..........value typeinfo, if available
+    RETURN VALUE:
+        true.............everything ok
+          false............an exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ bool resolve_constrain_unresolved_field(unresolved_field *ref,
+                                                                               classinfo *referer, 
+                                                                               methodinfo *refmethod,
+                                                                           typeinfo_t *instanceti,
+                                                                           typeinfo_t *valueti)
+ {
+       constant_FMIref *fieldref;
+       int type;
+       typeinfo_t tinfo;
+       typedesc *fd;
+       assert(ref);
+       fieldref = ref->fieldref;
+       assert(fieldref);
+ #ifdef RESOLVE_VERBOSE
+       printf("constrain_unresolved_field\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+       printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+       printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+ /*    printf("    class  : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout); */
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+       printf("    desc   : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
+       printf("    type   : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
+       fputc('\n',stdout);
+ #endif
+       assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
+       fd = fieldref->parseddesc.fd;
+       assert(fd);
+       /* record subtype constraints for the instance type, if any */
+       if (instanceti) {
+               typeinfo_t *insttip;
+               /* The instanceslot must contain a reference to a non-array type */
+               if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, 
+                                       "illegal instruction: field access on non-reference");
+                       return false;
+               }
+               if (TYPEINFO_IS_ARRAY(*instanceti)) {
+                       exceptions_throw_verifyerror(refmethod, 
+                                       "illegal instruction: field access on array");
+                       return false;
+               }
+               if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
+                               TYPEINFO_IS_NEWOBJECT(*instanceti))
+               {
+                       /* The instruction writes a field in an uninitialized object. */
+                       /* This is only allowed when a field of an uninitialized 'this' object is */
+                       /* written inside an initialization method                                */
+                       classinfo *initclass;
+                       instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+                       if (ins != NULL) {
+                               exceptions_throw_verifyerror(refmethod, 
+                                               "accessing field of uninitialized object");
+                               return false;
+                       }
+                       /* XXX check that class of field == refmethod->clazz */
+                       initclass = refmethod->clazz; /* XXX classrefs */
+                       assert(initclass->state & CLASS_LOADED);
+                       assert(initclass->state & CLASS_LINKED);
+                       typeinfo_init_classinfo(&tinfo, initclass);
+                       insttip = &tinfo;
+               }
+               else {
+                       insttip = instanceti;
+               }
+               if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+                                       &(ref->instancetypes), insttip, 
+                                       FIELDREF_CLASSNAME(fieldref)))
+                       return false;
+       }
+       else {
+               UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
+       }
+       /* record subtype constraints for the value type, if any */
+       type = fd->type;
+       if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
+               assert(valueti);
+               if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+                                       &(ref->valueconstraints), valueti, 
+                                       fieldref->parseddesc.fd->classref->name))
+                       return false;
+       }
+       else {
+               UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
+       }
+       return true;
+ }
+ #endif /* ENABLE_VERIFIER */
+ /* resolve_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 * resolve_create_unresolved_method(classinfo *referer,
+                                                                                                        methodinfo *refmethod,
+                                                                                                        constant_FMIref *methodref,
+                                                                                                        bool invokestatic,
+                                                                                                        bool invokespecial)
+ {
+       unresolved_method *ref;
+       assert(methodref);
+ #ifdef RESOLVE_VERBOSE
+       printf("create_unresolved_method\n");
+       printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+       printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+       printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+       printf("    name   : ");utf_fprint_printable_ascii(stdout,methodref->name);fputc('\n',stdout);
+       printf("    desc   : ");utf_fprint_printable_ascii(stdout,methodref->descriptor);fputc('\n',stdout);
+ #endif
+       /* allocate params if necessary */
+       if (!methodref->parseddesc.md->params)
+               if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
+                                       (invokestatic) ? ACC_STATIC : ACC_NONE))
+                       return NULL;
+       /* create the data structure */
+       ref = NEW(unresolved_method);
+       ref->flags = ((invokestatic) ? RESOLVE_STATIC : 0)
+                          | ((invokespecial) ? RESOLVE_SPECIAL : 0);
+       ref->referermethod = refmethod;
+       ref->methodref = methodref;
+       ref->paramconstraints = NULL;
+       UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
+       return ref;
+ }
+ /* resolve_constrain_unresolved_method_instance ********************************
+  
+    Record subtype constraints for the instance argument of a method call.
+   
+    IN:
+        ref..............the unresolved_method structure of the call
+        referer..........the class containing the reference
+          refmethod........the method triggering the resolution (if any)
+          iptr.............the INVOKE* instruction
+    RETURN VALUE:
+        true.............everything ok
+          false............an exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
+                                                                                                 methodinfo *refmethod,
+                                                                                                 typeinfo_t *instanceti,
+                                                                                                 bool invokespecial)
+ {
+       constant_FMIref   *methodref;
+       constant_classref *instanceref;
+       typeinfo_t           tinfo;
+       typeinfo_t          *tip;
+       assert(ref);
+       methodref = ref->methodref;
+       assert(methodref);
+       /* XXX clean this up */
+       instanceref = IS_FMIREF_RESOLVED(methodref)
+               ? class_get_self_classref(methodref->p.method->clazz)
+               : methodref->p.classref;
+ #ifdef RESOLVE_VERBOSE
+       printf("resolve_constrain_unresolved_method_instance\n");
+       printf("    rmethod: "); method_println(refmethod);
+       printf("    mref   : "); method_methodref_println(methodref);
+ #endif
+       /* record subtype constraints for the instance type, if any */
+       if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
+       {   /* XXX clean up */
+               instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
+               classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
+                                                                        : CLASSREF_OR_CLASSINFO(refmethod->clazz);
+               tip = &tinfo;
+               if (!typeinfo_init_class(tip, initclass))
+                       return false;
+       }
+       else {
+               tip = instanceti;
+       }
+       if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+                               &(ref->instancetypes),tip,instanceref->name))
+               return false;
+       return true;
+ }
+ #endif /* defined(ENABLE_VERIFIER) */
+ /* resolve_constrain_unresolved_method_params  *********************************
+  
+    Record subtype constraints for the non-instance arguments of a method call.
+   
+    IN:
+        jd...............current jitdata (for looking up variables)
+        ref..............the unresolved_method structure of the call
+          refmethod........the method triggering the resolution (if any)
+          iptr.............the INVOKE* instruction
+    RETURN VALUE:
+        true.............everything ok
+          false............an exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ bool resolve_constrain_unresolved_method_params(jitdata *jd,
+                                                                                               unresolved_method *ref,
+                                                                                               methodinfo *refmethod,
+                                                                                               instruction *iptr)
+ {
+       constant_FMIref *methodref;
+       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;
+               assert(param);
+               assert(type == param->type);
+               if (type == TYPE_ADR) {
+                       if (!ref->paramconstraints) {
+                               ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
+                               for (j=md->paramcount-1-instancecount; j>i; --j)
+                                       UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
+                       }
+                       assert(ref->paramconstraints);
+                       if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+                                               ref->paramconstraints + i,&(param->typeinfo),
+                                               md->paramtypes[i+instancecount].classref->name))
+                               return false;
+               }
+               else {
+                       if (ref->paramconstraints)
+                               UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
+               }
+       }
+       return true;
+ }
+ #endif /* ENABLE_VERIFIER */
+ /* resolve_constrain_unresolved_method_params_stackbased ***********************
+  
+    Record subtype constraints for the non-instance arguments of a method call.
+   
+    IN:
+        ref..............the unresolved_method structure of the call
+          refmethod........the method triggering the resolution (if any)
+          stack............TOS before the INVOKE instruction
+    RETURN VALUE:
+        true.............everything ok
+          false............an exception has been thrown
+ *******************************************************************************/
+ #if defined(ENABLE_VERIFIER)
+ bool resolve_constrain_unresolved_method_params_stackbased(
+               unresolved_method *ref,
+               methodinfo *refmethod,
+               typedescriptor_t *stack)
+ {
+       constant_FMIref *methodref;
+       typedescriptor_t *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->clazz, 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                                                             */
+ /******************************************************************************/
+ #ifdef ENABLE_VERIFIER
+ inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
+ {
+       if (list) {
+               classref_or_classinfo *p = list;
+               /* this is silly. we *only* need to count the elements for MFREE */
+               while ((p++)->any)
+                       ;
+               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 *******************************************************
+  
+    Free the memory used by an unresolved_field
+   
+    IN:
+        ref..............the unresolved_field
+ *******************************************************************************/
+ void unresolved_field_free(unresolved_field *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);
+ }
+ /* unresolved_method_free ******************************************************
+  
+    Free the memory used by an unresolved_method
+   
+    IN:
+        ref..............the unresolved_method
+ *******************************************************************************/
+ void unresolved_method_free(unresolved_method *ref)
+ {
+       assert(ref);
+ #ifdef ENABLE_VERIFIER
+       unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
+       if (ref->paramconstraints) {
+               int i;
+               int count = ref->methodref->parseddesc.md->paramcount;
+               for (i=0; i<count; ++i)
+                       unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
+               MFREE(ref->paramconstraints,unresolved_subtype_set,count);
+       }
+ #endif
+       FREE(ref,unresolved_method);
+ }
+ /******************************************************************************/
+ /* DEBUG DUMPS                                                                */
+ /******************************************************************************/
+ #if !defined(NDEBUG)
+ /* unresolved_subtype_set_debug_dump *******************************************
+  
+    Print debug info for unresolved_subtype_set to stream
+   
+    IN:
+        stset............the unresolved_subtype_set
+          file.............the stream
+ *******************************************************************************/
+ void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
+ {
+       classref_or_classinfo *p;
+       if (SUBTYPESET_IS_EMPTY(*stset)) {
+               fprintf(file,"        (empty)\n");
+       }
+       else {
+               p = stset->subtyperefs;
+               for (;p->any; ++p) {
+                       if (IS_CLASSREF(*p)) {
+                               fprintf(file,"        ref: ");
+                               utf_fprint_printable_ascii(file,p->ref->name);
+                       }
+                       else {
+                               fprintf(file,"        cls: ");
+                               utf_fprint_printable_ascii(file,p->cls->name);
+                       }
+                       fputc('\n',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_printable_ascii(file,ref->classref->referer->name); fputc('\n',file);
+               fprintf(file,"    refmethod : ");
+               utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
+               fprintf(file,"    refmethodd: ");
+               utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
+               fprintf(file,"    classname : ");
+               utf_fprint_printable_ascii(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
+   
+    IN:
+        ref..............the unresolved_field
+          file.............the stream
+ *******************************************************************************/
+ 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_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
+               fprintf(file,"    refmethod : ");
+               utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
+               fprintf(file,"    refmethodd: ");
+               utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
+               fprintf(file,"    classname : ");
+               utf_fprint_printable_ascii(file,FIELDREF_CLASSNAME(ref->fieldref)); fputc('\n',file);
+               fprintf(file,"    name      : ");
+               utf_fprint_printable_ascii(file,ref->fieldref->name); fputc('\n',file);
+               fprintf(file,"    descriptor: ");
+               utf_fprint_printable_ascii(file,ref->fieldref->descriptor); fputc('\n',file);
+               fprintf(file,"    parseddesc: ");
+               descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
+               fprintf(file,"    flags     : %04x\n",ref->flags);
+               fprintf(file,"    instancetypes:\n");
+               unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
+               fprintf(file,"    valueconstraints:\n");
+               unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
+       }
+ }
+ /* unresolved_method_debug_dump ************************************************
+  
+    Print debug info for unresolved_method to stream
+   
+    IN:
+        ref..............the unresolved_method
+          file.............the stream
+ *******************************************************************************/
+ void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
+ {
+       int i;
+       fprintf(file,"unresolved_method(%p):\n",(void *)ref);
+       if (ref) {
+               fprintf(file,"    referer   : ");
+               utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
+               fprintf(file,"    refmethod : ");
+               utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
+               fprintf(file,"    refmethodd: ");
+               utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
+               fprintf(file,"    classname : ");
+               utf_fprint_printable_ascii(file,METHODREF_CLASSNAME(ref->methodref)); fputc('\n',file);
+               fprintf(file,"    name      : ");
+               utf_fprint_printable_ascii(file,ref->methodref->name); fputc('\n',file);
+               fprintf(file,"    descriptor: ");
+               utf_fprint_printable_ascii(file,ref->methodref->descriptor); fputc('\n',file);
+               fprintf(file,"    parseddesc: ");
+               descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
+               fprintf(file,"    flags     : %04x\n",ref->flags);
+               fprintf(file,"    instancetypes:\n");
+               unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
+               fprintf(file,"    paramconstraints:\n");
+               if (ref->paramconstraints) {
+                       for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
+                               fprintf(file,"      param %d:\n",i);
+                               unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
+                       }
+               }
+               else {
+                       fprintf(file,"      (empty)\n");
+               }
+       }
+ }
+ #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
+  * Emacs will automagically detect them.
+  * ---------------------------------------------------------------------
+  * Local variables:
+  * mode: c
+  * indent-tabs-mode: t
+  * c-basic-offset: 4
+  * tab-width: 4
+  * End:
+  * vim:noexpandtab:sw=4:ts=4:
+  */
index 46aa681f7e8bec6aee5d0e9853273aaa239cc87f,c23a737cc2d2127a7c7bb73d8971659959dc5971..8ab2f6fd509fee91404cca97fe80ad1577e98f24
@@@ -46,9 -46,7 +46,9 @@@
  
  #include "toolbox/logging.h"
  
- #include "vm/class.h"
 +#include "threads/thread.hpp"
 +
+ #include "vm/class.hpp"
  #include "vm/field.hpp"
  #include "vm/global.h"
  #include "vm/method.h"
diff --cc src/vm/vm.cpp
Simple merge