* Removed all Id tags.
[cacao.git] / src / vm / jit / verify / typeinfo.c
index 4b943bf9d73dbc499b5e5881aae0582178159e39..3d0a47888fc582644cd9ca2a1e5292a6735a8e8e 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/verify/typeinfo.c - type system used by the type checker
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Edwin Steiner
+*/
 
-   $Id: typeinfo.c 2181 2005-04-01 16:53:33Z edwin $
 
-*/
+#include "config.h"
 
 #include <assert.h>
 #include <string.h>
 
 #include "mm/memory.h"
+
 #include "toolbox/logging.h"
-#include "vm/class.h"
-#include "vm/loader.h"
-#include "vm/tables.h"
+
+#include "vm/array.h"
+#include "vm/exceptions.h"
+#include "vm/primitive.h"
+#include "vm/resolve.h"
+
 #include "vm/jit/jit.h"
 #include "vm/jit/verify/typeinfo.h"
-#include "vm/descriptor.h"
-#include "vm/resolve.h"
+
+#include "vmcore/class.h"
+#include "vmcore/descriptor.h"
+#include "vmcore/loader.h"
 
 
 /* check if a linked class is an array class. Only use for linked classes! */
 #define CLASSINFO_IS_ARRAY(clsinfo)  ((clsinfo)->vftbl->arraydesc != NULL)
 
+/* check if a linked class implements the interface with the given index */
 #define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index)                   \
     ( ((index) < (cls)->vftbl->interfacetablelength)            \
-      && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
+      && ( (cls)->vftbl->interfacetable[-(index)] != NULL ) )
 
 /******************************************************************************/
 /* DEBUG HELPERS                                                              */
 /* TYPEVECTOR FUNCTIONS                                               */
 /**********************************************************************/
 
-typevector *
-typevectorset_copy(typevector *src,int k,int size)
+#if defined(ENABLE_VERIFIER)
+
+/* typevector_copy *************************************************************
+   Return a copy of the given typevector.
+  
+   IN:
+          src..............typevector set to copy, must be != NULL
+          size.............number of elements per typevector
+
+   RETURN VALUE:
+       a pointer to the new typevector set
+
+*******************************************************************************/
+
+varinfo *
+typevector_copy(varinfo *src, int size)
 {
-       typevector *dst = DNEW_TYPEVECTOR(size);
+       varinfo *dst;
        
+       TYPEINFO_ASSERT(src);
+       
+       dst = DNEW_TYPEVECTOR(size);
        memcpy(dst,src,TYPEVECTOR_SIZE(size));
-       dst->k = k;
-       if (src->alt)
-               dst->alt = typevectorset_copy(src->alt,k+1,size);
+
        return dst;
 }
 
-bool
-typevectorset_checktype(typevector *vec,int index,int type)
+/* typevector_copy_inplace *****************************************************
+   Copy a typevector to a given destination.
+
+   IN:
+          src..............typevector to copy, must be != NULL
+          dst..............destination to write the copy to
+          size.............number of elements per typevector
+
+*******************************************************************************/
+
+void
+typevector_copy_inplace(varinfo *src,varinfo *dst,int size)
 {
-       do {
-               if (vec->td[index].type != type)
-                       return false;
-       } while ((vec = vec->alt) != NULL);
-       return true;
+       memcpy(dst,src,TYPEVECTOR_SIZE(size));
 }
 
+/* typevector_checktype ********************************************************
+   Check if the typevector contains a given type at a given index.
+  
+   IN:
+          vec..............typevector set, must be != NULL
+          index............index of component to check
+          type.............TYPE_* constant to check against
+
+   RETURN VALUE:
+       true if the typevector contains TYPE at INDEX,
+          false otherwise
+
+*******************************************************************************/
+
 bool
-typevectorset_checkreference(typevector *vec,int index)
+typevector_checktype(varinfo *vec,int index,int type)
 {
-       do {
-               if (!TYPEDESC_IS_REFERENCE(vec->td[index]))
-                       return false;
-       } while ((vec = vec->alt) != NULL);
-       return true;
+       TYPEINFO_ASSERT(vec);
+
+       return vec[index].type == type;
 }
 
+/* typevector_checkreference ***************************************************
+   Check if the typevector contains a reference at a given index.
+  
+   IN:
+          vec..............typevector, must be != NULL
+          index............index of component to check
+
+   RETURN VALUE:
+       true if the typevector contains a reference at INDEX,
+          false otherwise
+
+*******************************************************************************/
+
 bool
-typevectorset_checkretaddr(typevector *vec,int index)
+typevector_checkreference(varinfo *vec, int index)
 {
-       do {
-               if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index]))
-                       return false;
-       } while ((vec = vec->alt) != NULL);
-       return true;
+       TYPEINFO_ASSERT(vec);
+       return TYPEDESC_IS_REFERENCE(vec[index]);
 }
 
-int
-typevectorset_copymergedtype(typevector *vec,int index,typeinfo *dst)
-{
-       int type;
-       typedescriptor *td;
+/* typevectorset_checkretaddr **************************************************
+   Check if the typevectors contains a returnAddress at a given index.
+  
+   IN:
+          vec..............typevector, must be != NULL
+          index............index of component to check
 
-       td = vec->td + index;
-       type = td->type;
-       TYPEINFO_COPY(td->info,*dst);
-       
-       if (vec->alt) {
-               int primitive;
-               
-               primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0;
-               
-               while ((vec = vec->alt) != NULL) {
-                       td = vec->td + index;
-                       if (type != td->type)
-                               return TYPE_VOID;
-
-                       if (type == TYPE_ADDRESS) {
-                               if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive)
-                                       return TYPE_VOID;
-                               typeinfo_merge(dst,&(td->info));
-                       }
-               }
-       }
-       return type;
-}
-
-int
-typevectorset_mergedtype(typevector *vec,int index,typeinfo *temp,typeinfo **result)
-{
-       if (vec->alt) {
-               *result = temp;
-               return typevectorset_copymergedtype(vec,index,temp);
-       }
+   RETURN VALUE:
+       true if the typevector contains a returnAddress at INDEX,
+          false otherwise
 
-       *result = &(vec->td[index].info);
-       return vec->td[index].type;
-}
+*******************************************************************************/
 
-typeinfo *
-typevectorset_mergedtypeinfo(typevector *vec,int index,typeinfo *temp)
+bool
+typevector_checkretaddr(varinfo *vec,int index)
 {
-       typeinfo *result;
-       int type = typevectorset_mergedtype(vec,index,temp,&result);
-       return (type == TYPE_ADDRESS) ? result : NULL;
+       TYPEINFO_ASSERT(vec);
+       return TYPEDESC_IS_RETURNADDRESS(vec[index]);
 }
 
+/* typevector_store ************************************************************
+   Store a type at a given index in the typevector.
+  
+   IN:
+          vec..............typevector set, must be != NULL
+          index............index of component to set
+          type.............TYPE_* constant of type to set
+          info.............typeinfo of type to set, may be NULL, 
+                           if TYPE != TYPE_ADR
+
+*******************************************************************************/
+
 void
-typevectorset_store(typevector *vec,int index,int type,typeinfo *info)
+typevector_store(varinfo *vec,int index,int type,typeinfo *info)
 {
-       do {
-               vec->td[index].type = type;
-               if (info)
-                       TYPEINFO_COPY(*info,vec->td[index].info);
-               if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
-                       vec->td[index-1].type = TYPE_VOID;
-       } while ((vec = vec->alt) != NULL);
+       TYPEINFO_ASSERT(vec);
+
+       vec[index].type = type;
+       if (info)
+               TYPEINFO_COPY(*info,vec[index].typeinfo);
 }
 
+/* typevector_store_retaddr ****************************************************
+   Store a returnAddress type at a given index in the typevector.
+  
+   IN:
+          vec..............typevector set, must be != NULL
+          index............index of component to set
+          info.............typeinfo of the returnAddress.
+
+*******************************************************************************/
+
 void
-typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info)
+typevector_store_retaddr(varinfo *vec,int index,typeinfo *info)
 {
-       typeinfo_retaddr_set *adr;
+       TYPEINFO_ASSERT(vec);
+       TYPEINFO_ASSERT(TYPEINFO_IS_PRIMITIVE(*info));
        
-       adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info);
-       do {
-               vec->td[index].type = TYPE_ADDRESS;
-               TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr);
-               if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
-                       vec->td[index-1].type = TYPE_VOID;
-               adr = adr->alt;
-       } while ((vec = vec->alt) != NULL);
+       vec[index].type = TYPE_ADR;
+       TYPEINFO_INIT_RETURNADDRESS(vec[index].typeinfo,
+                       TYPEINFO_RETURNADDRESS(*info));
 }
 
-void
-typevectorset_store_twoword(typevector *vec,int index,int type)
-{
-       do {
-               vec->td[index].type = type;
-               vec->td[index+1].type = TYPE_VOID;
-               if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
-                       vec->td[index-1].type = TYPE_VOID;
-       } while ((vec = vec->alt) != NULL);
-}
+/* typevector_init_object ******************************************************
+   Replace all uninitialized object types in the typevector set which were 
+   created by the given instruction by initialized object types.
+  
+   IN:
+          set..............typevector set
+          ins..............instruction which created the uninitialized object type
+          initclass........class of the initialized object type to set
+          size.............number of elements per typevector
 
-void
-typevectorset_init_object(typevector *set,void *ins,
-                                                 classref_or_classinfo initclass,
-                                                 int size)
+   RETURN VALUE:
+       true.............success
+          false............an exception has been thrown
+
+   XXX maybe we should do the lazy resolving before calling this function
+
+*******************************************************************************/
+
+bool
+typevector_init_object(varinfo *set,void *ins,
+                                          classref_or_classinfo initclass,
+                                          int size)
 {
        int i;
-       
-       for (;set; set=set->alt) {
-               for (i=0; i<size; ++i) {
-                       if (set->td[i].type == TYPE_ADR
-                               && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
-                               && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
-                       {
-                               TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(set->td[i].info,initclass);
-                       }
+
+       for (i=0; i<size; ++i) {
+               if (set[i].type == TYPE_ADR
+                       && TYPEINFO_IS_NEWOBJECT(set[i].typeinfo)
+                       && TYPEINFO_NEWOBJECT_INSTRUCTION(set[i].typeinfo) == ins)
+               {
+                       if (!typeinfo_init_class(&(set[i].typeinfo),initclass))
+                               return false;
                }
        }
+       return true;
 }
 
-bool
-typevector_merge(typevector *dst,typevector *y,int size)
+/* typevector_merge ************************************************************
+   Merge a typevector with another one.
+   The given typevectors must have the same number of components.
+  
+   IN:
+       m................method for exception messages
+          dst..............the first typevector
+          y................the second typevector
+          size.............number of elements per typevector
+
+   OUT:
+       *dst.............the resulting typevector
+
+   RETURN VALUE:
+       typecheck_TRUE...dst has been modified
+          typecheck_FALSE..dst has not been modified
+          typecheck_FAIL...an exception has been thrown
+
+*******************************************************************************/
+
+typecheck_result
+typevector_merge(methodinfo *m,varinfo *dst,varinfo *y,int size)
 {
        bool changed = false;
+       typecheck_result r;
        
-       typedescriptor *a = dst->td;
-       typedescriptor *b = y->td;
+       varinfo *a = dst;
+       varinfo *b = y;
        while (size--) {
                if (a->type != TYPE_VOID && a->type != b->type) {
                        a->type = TYPE_VOID;
                        changed = true;
                }
-               else if (a->type == TYPE_ADDRESS) {
-                       if (TYPEINFO_IS_PRIMITIVE(a->info)) {
+               else if (a->type == TYPE_ADR) {
+                       if (TYPEINFO_IS_PRIMITIVE(a->typeinfo)) {
                                /* 'a' is a returnAddress */
-                               if (!TYPEINFO_IS_PRIMITIVE(b->info)
-                                       || (TYPEINFO_RETURNADDRESS(a->info)
-                                               != TYPEINFO_RETURNADDRESS(b->info)))
+                               if (!TYPEINFO_IS_PRIMITIVE(b->typeinfo)
+                                       || (TYPEINFO_RETURNADDRESS(a->typeinfo)
+                                               != TYPEINFO_RETURNADDRESS(b->typeinfo)))
                                {
                                        a->type = TYPE_VOID;
                                        changed = true;
@@ -239,12 +309,17 @@ typevector_merge(typevector *dst,typevector *y,int size)
                        }
                        else {
                                /* 'a' is a reference */
-                               if (TYPEINFO_IS_PRIMITIVE(b->info)) {
+                               if (TYPEINFO_IS_PRIMITIVE(b->typeinfo)) {
                                        a->type = TYPE_VOID;
                                        changed = true;
                                }
                                else {
-                                       changed |= typeinfo_merge(&(a->info),&(b->info));
+                                       /* two reference types are merged. There cannot be */
+                                       /* a merge error. In the worst case we get j.l.O.  */
+                                       r = typeinfo_merge(m,&(a->typeinfo),&(b->typeinfo));
+                                       if (r == typecheck_FAIL)
+                                               return r;
+                                       changed |= r;
                                }
                        }
                }
@@ -254,97 +329,23 @@ typevector_merge(typevector *dst,typevector *y,int size)
        return changed;
 }
 
-bool 
-typevector_separable_from(typevector *a,typevector *b,int size)
-{
-       typedescriptor *tda = a->td;
-       typedescriptor *tdb = b->td;
-       for (;size--; tda++,tdb++) {
-               if (TYPEDESC_IS_RETURNADDRESS(*tda)
-                       && TYPEDESC_IS_RETURNADDRESS(*tdb)
-                       && TYPEINFO_RETURNADDRESS(tda->info)
-                          != TYPEINFO_RETURNADDRESS(tdb->info))
-                       return true;
-       }
-       return false;
-}
-
-void
-typevectorset_add(typevector *dst,typevector *v,int size)
-{
-       while (dst->alt)
-               dst = dst->alt;
-       dst->alt = DNEW_TYPEVECTOR(size);
-       memcpy(dst->alt,v,TYPEVECTOR_SIZE(size));
-       dst->alt->alt = NULL;
-       dst->alt->k = dst->k + 1;
-}
-
-typevector *
-typevectorset_select(typevector **set,int retindex,void *retaddr)
-{
-       typevector *selected;
-
-       if (!*set) return NULL;
-       
-       if (TYPEINFO_RETURNADDRESS((*set)->td[retindex].info) == retaddr) {
-               selected = *set;
-               *set = selected->alt;
-               selected->alt = typevectorset_select(set,retindex,retaddr);
-       }
-       else {
-               selected = typevectorset_select(&((*set)->alt),retindex,retaddr);
-       }
-       return selected;
-}
-
-bool
-typevectorset_separable_with(typevector *set,typevector *add,int size)
-{
-       int i;
-       typevector *v;
-       void *addr;
-       bool separable;
-
-       for (i=0; i<size; ++i) {
-               if (!TYPEDESC_IS_RETURNADDRESS(add->td[i]))
-                       continue;
-               addr = TYPEINFO_RETURNADDRESS(add->td[i].info);
-               
-               v = set;
-               separable = false;
-               do {
-                       if (!TYPEDESC_IS_RETURNADDRESS(v->td[i]))
-                               goto next_index;
-                       if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr)
-                               separable = true;
-                       v = v->alt;
-                       if (!v && separable) return true;
-               } while (v);
-       next_index:
-               ;
-       }
-       return false;
-}
-
-bool
-typevectorset_collapse(typevector *dst,int size)
-{
-       bool changed = false;
-       
-       while (dst->alt) {
-               typevector_merge(dst,dst->alt,size);
-               dst->alt = dst->alt->alt;
-               changed = true;
-       }
-       return changed;
-}
-
 /**********************************************************************/
 /* READ-ONLY FUNCTIONS                                                */
 /* The following functions don't change typeinfo data.                */
 /**********************************************************************/
 
+/* typeinfo_is_array ***********************************************************
+   Check whether a typeinfo describes an array type.
+   
+   IN:
+          info.............the typeinfo, must be != NULL
+
+   RETURN VALUE:
+       true if INFO describes an array type.
+
+*******************************************************************************/
+
 bool
 typeinfo_is_array(typeinfo *info)
 {
@@ -352,6 +353,18 @@ typeinfo_is_array(typeinfo *info)
     return TYPEINFO_IS_ARRAY(*info);
 }
 
+/* typeinfo_is_primitive_array *************************************************
+   Check whether a typeinfo describes a primitive array type.
+   
+   IN:
+          info.............the typeinfo, must be != NULL
+
+   RETURN VALUE:
+       true if INFO describes an array of a primitive type.
+
+*******************************************************************************/
+
 bool
 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
 {
@@ -359,6 +372,18 @@ typeinfo_is_primitive_array(typeinfo *info,int arraytype)
     return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
 }
 
+/* typeinfo_is_array_of_refs ***************************************************
+   Check whether a typeinfo describes an array of references type.
+   
+   IN:
+          info.............the typeinfo, must be != NULL
+
+   RETURN VALUE:
+       true if INFO describes an array of a refrence type.
+
+*******************************************************************************/
+
 bool
 typeinfo_is_array_of_refs(typeinfo *info)
 {
@@ -366,6 +391,20 @@ typeinfo_is_array_of_refs(typeinfo *info)
     return TYPEINFO_IS_ARRAY_OF_REFS(*info);
 }
 
+/* interface_extends_interface *************************************************
+   Check if a resolved interface extends a given resolved interface.
+   
+   IN:
+          cls..............the interface, must be linked
+          interf...........the interface to check against
+
+   RETURN VALUE:
+       true.............CLS extends INTERF
+          false............CLS does not extend INTERF
+
+*******************************************************************************/
+
 static bool
 interface_extends_interface(classinfo *cls,classinfo *interf)
 {
@@ -375,62 +414,95 @@ interface_extends_interface(classinfo *cls,classinfo *interf)
        TYPEINFO_ASSERT(interf);
        TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
        TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
+       TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
 
     /* first check direct superinterfaces */
     for (i=0; i<cls->interfacescount; ++i) {
-        if (cls->interfaces[i] == interf)
+        if (cls->interfaces[i].cls == interf)
             return true;
     }
     
     /* check indirect superinterfaces */
     for (i=0; i<cls->interfacescount; ++i) {
-        if (interface_extends_interface(cls->interfaces[i],interf))
+        if (interface_extends_interface(cls->interfaces[i].cls,interf))
             return true;
     }
     
     return false;
 }
 
-static bool
+/* classinfo_implements_interface **********************************************
+   Check if a resolved class implements a given resolved interface.
+   
+   IN:
+          cls..............the class
+          interf...........the interface
+
+   RETURN VALUE:
+       typecheck_TRUE...CLS implements INTERF
+          typecheck_FALSE..CLS does not implement INTERF
+          typecheck_FAIL...an exception has been thrown
+
+*******************************************************************************/
+
+static typecheck_result
 classinfo_implements_interface(classinfo *cls,classinfo *interf)
 {
        TYPEINFO_ASSERT(cls);
        TYPEINFO_ASSERT(interf);
        TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
 
-       if (!cls->loaded)
-               if (!load_class_bootstrap(cls)) /* XXX */
-                       return false;
-
-       if (!cls->linked)
-               if (!link_class(cls)) /* XXX */
-                       return false;
+       if (!(cls->state & CLASS_LINKED))
+               if (!link_class(cls))
+                       return typecheck_FAIL;
 
     if (cls->flags & ACC_INTERFACE) {
         /* cls is an interface */
         if (cls == interf)
-            return true;
+            return typecheck_TRUE;
 
         /* check superinterfaces */
         return interface_extends_interface(cls,interf);
     }
 
+       TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
     return CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
 }
 
-tristate_t 
+/* mergedlist_implements_interface *********************************************
+   Check if all the classes in a given merged list implement a given resolved
+   interface.
+   
+   IN:
+          merged...........the list of merged class types
+          interf...........the interface to check against
+
+   RETURN VALUE:
+       typecheck_TRUE...all classes implement INTERF
+          typecheck_FALSE..there is at least one class that does not implement
+                           INTERF
+          typecheck_MAYBE..check cannot be performed now because of unresolved
+                           classes
+          typecheck_FAIL...an exception has been thrown
+
+*******************************************************************************/
+
+static typecheck_result
 mergedlist_implements_interface(typeinfo_mergedlist *merged,
                                 classinfo *interf)
 {
     int i;
     classref_or_classinfo *mlist;
+       typecheck_result r;
     
        TYPEINFO_ASSERT(interf);
        TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
 
     /* Check if there is an non-empty mergedlist. */
     if (!merged)
-        return false;
+        return typecheck_FALSE;
 
     /* If all classinfos in the (non-empty) merged array implement the
      * interface return true, otherwise false.
@@ -439,45 +511,147 @@ mergedlist_implements_interface(typeinfo_mergedlist *merged,
     i = merged->count;
     while (i--) {
                if (IS_CLASSREF(*mlist)) {
-                       return MAYBE;
+                       return typecheck_MAYBE;
                }
-        if (!classinfo_implements_interface((mlist++)->cls,interf))
-            return false;
+        r = classinfo_implements_interface((mlist++)->cls,interf);
+        if (r != typecheck_TRUE)
+                       return r;
     }
-    return true;
+    return typecheck_TRUE;
 }
 
-tristate_t
+/* merged_implements_interface *************************************************
+   Check if a possible merged type implements a given resolved interface
+   interface.
+   
+   IN:
+       typeclass........(common) class of the (merged) type
+          merged...........the list of merged class types
+          interf...........the interface to check against
+
+   RETURN VALUE:
+       typecheck_TRUE...the type implement INTERF
+          typecheck_FALSE..the type does not implement INTERF
+          typecheck_MAYBE..check cannot be performed now because of unresolved
+                           classes
+          typecheck_FAIL...an exception has been thrown
+
+*******************************************************************************/
+
+static typecheck_result
 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
                             classinfo *interf)
 {
+       typecheck_result r;
+       
     /* primitive types don't support interfaces. */
     if (!typeclass)
-        return false;
+        return typecheck_FALSE;
 
     /* the null type can be cast to any interface type. */
     if (typeclass == pseudo_class_Null)
-        return true;
+        return typecheck_TRUE;
 
     /* check if typeclass implements the interface. */
-    if (classinfo_implements_interface(typeclass,interf))
-        return true;
+    r = classinfo_implements_interface(typeclass,interf);
+       if (r != typecheck_FALSE)
+        return r;
 
     /* check the mergedlist */
-    return (merged && mergedlist_implements_interface(merged,interf));
+       if (!merged)
+               return typecheck_FALSE;
+    return mergedlist_implements_interface(merged,interf);
 }
 
-tristate_t
-typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
+/* merged_is_subclass **********************************************************
+   Check if a possible merged type is a subclass of a given class.
+   A merged type is a subclass of a class C if all types in the merged list
+   are subclasses of C. A sufficient condition for this is that the
+   common type of the merged type is a subclass of C.
+
+   IN:
+       typeclass........(common) class of the (merged) type
+                           MUST be a loaded and linked class
+          merged...........the list of merged class types
+          cls..............the class to theck against
+
+   RETURN VALUE:
+       typecheck_TRUE...the type is a subclass of CLS
+          typecheck_FALSE..the type is not a subclass of CLS
+          typecheck_MAYBE..check cannot be performed now because of unresolved
+                           classes
+          typecheck_FAIL...an exception has been thrown
+
+*******************************************************************************/
+
+static typecheck_result
+merged_is_subclass(classinfo *typeclass,typeinfo_mergedlist *merged,
+               classinfo *cls)
 {
-       TYPEINFO_ASSERT(value);
-       TYPEINFO_ASSERT(dest);
-       TYPEINFO_ASSERT(dest->merged == NULL);
+    int i;
+    classref_or_classinfo *mlist;
 
-       return typeinfo_is_assignable_to_class(value,dest->typeclass);
+       TYPEINFO_ASSERT(cls);
+       
+    /* primitive types aren't subclasses of anything. */
+    if (!typeclass)
+        return typecheck_FALSE;
+
+    /* the null type can be cast to any reference type. */
+    if (typeclass == pseudo_class_Null)
+        return typecheck_TRUE;
+
+       TYPEINFO_ASSERT(typeclass->state & CLASS_LOADED);
+       TYPEINFO_ASSERT(typeclass->state & CLASS_LINKED);
+
+    /* check if the common typeclass is a subclass of CLS. */
+       if (class_issubclass(typeclass,cls))
+               return typecheck_TRUE;
+       
+    /* check the mergedlist */
+       if (!merged)
+               return typecheck_FALSE;
+    /* If all classinfos in the (non-empty) merged list are subclasses
+        * of CLS, return true, otherwise false.
+        * If there is at least one unresolved type in the list,
+        * return typecheck_MAYBE.
+     */
+    mlist = merged->list;
+    i = merged->count;
+    while (i--) {
+               if (IS_CLASSREF(*mlist)) {
+                       return typecheck_MAYBE;
+               }
+               if (!(mlist->cls->state & CLASS_LINKED))
+                       if (!link_class(mlist->cls))
+                               return typecheck_FAIL;
+               if (!class_issubclass(mlist->cls,cls))
+                       return typecheck_FALSE;
+               mlist++;
+    }
+    return typecheck_TRUE;
 }
 
-tristate_t
+/* typeinfo_is_assignable_to_class *********************************************
+   Check if a type is assignable to a given class type.
+   
+   IN:
+       value............the type of the value
+          dest.............the type of the destination
+
+   RETURN VALUE:
+       typecheck_TRUE...the type is assignable
+          typecheck_FALSE..the type is not assignable
+          typecheck_MAYBE..check cannot be performed now because of unresolved
+                           classes
+          typecheck_FAIL...an exception has been thrown
+
+*******************************************************************************/
+
+typecheck_result
 typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
 {
        classref_or_classinfo c;
@@ -490,19 +664,19 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
 
     /* assignments of primitive values are not checked here. */
     if (!c.any && !dest.any)
-        return true;
+        return typecheck_TRUE;
 
     /* primitive and reference types are not assignment compatible. */
     if (!c.any || !dest.any)
-        return false;
+        return typecheck_FALSE;
 
     /* the null type can be assigned to any type */
     if (TYPEINFO_IS_NULLTYPE(*value))
-        return true;
+        return typecheck_TRUE;
 
     /* uninitialized objects are not assignable */
     if (TYPEINFO_IS_NEWOBJECT(*value))
-        return false;
+        return typecheck_FALSE;
 
        if (IS_CLASSREF(c)) {
                /* The value type is an unresolved class reference. */
@@ -518,11 +692,11 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
 
                /* the common case of value and dest type having the same classname */
                if (dest.ref->name == classname && !value->merged)
-                       return true;
+                       return typecheck_TRUE;
 
                /* we cannot tell if value is assignable to dest, so we */
                /* leave it up to the resolving code to check this      */
-               return MAYBE;
+               return typecheck_MAYBE;
        }
 
        /* { we know that dest is a loaded class } */
@@ -532,34 +706,35 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
                
                /* the common case of value and dest type having the same classname */
                if (dest.cls->name == classname)
-                       return true;
+                       return typecheck_TRUE;
 
                /* we cannot tell if value is assignable to dest, so we */
                /* leave it up to the resolving code to check this      */
-               return MAYBE;
+               return typecheck_MAYBE;
        }
 
        /* { we know that both c and dest are loaded classes } */
+       /* (c may still have a merged list containing unresolved classrefs!) */
+
+       TYPEINFO_ASSERT(!IS_CLASSREF(c));
+       TYPEINFO_ASSERT(!IS_CLASSREF(dest));
 
        cls = c.cls;
        
-       if (!cls->loaded)
-               load_class_bootstrap(cls); /* XXX */
-       if (!dest.cls->loaded)
-               load_class_bootstrap(dest.cls); /* XXX */
-
-       TYPEINFO_ASSERT(cls->loaded);
-       TYPEINFO_ASSERT(dest.cls->loaded);
+       TYPEINFO_ASSERT(cls->state & CLASS_LOADED);
+       TYPEINFO_ASSERT(dest.cls->state & CLASS_LOADED);
 
        /* maybe we need to link the classes */
-       if (!cls->linked)
-               link_class(cls); /* XXX */
-       if (!dest.cls->linked)
-               link_class(dest.cls); /* XXX */
+       if (!(cls->state & CLASS_LINKED))
+               if (!link_class(cls))
+                       return typecheck_FAIL;
+       if (!(dest.cls->state & CLASS_LINKED))
+               if (!link_class(dest.cls))
+                       return typecheck_FAIL;
 
        /* { we know that both c and dest are linked classes } */
-       TYPEINFO_ASSERT(cls->linked);
-       TYPEINFO_ASSERT(dest.cls->linked);
+       TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
+       TYPEINFO_ASSERT(dest.cls->state & CLASS_LINKED);
 
     if (dest.cls->flags & ACC_INTERFACE) {
         /* We are assigning to an interface type. */
@@ -574,20 +749,20 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
                        
         /* We are assigning to an array type. */
         if (!TYPEINFO_IS_ARRAY(*value))
-            return false;
+            return typecheck_FALSE;
 
         /* {Both value and dest.cls are array types.} */
 
         /* value must have at least the dimension of dest.cls. */
         if (value->dimension < dimension)
-            return false;
+            return typecheck_FALSE;
 
         if (value->dimension > dimension) {
             /* value has higher dimension so we need to check
              * if its component array can be assigned to the
              * element type of dest.cls */
 
-                       if (!elementclass) return false;
+                       if (!elementclass) return typecheck_FALSE;
             
             if (elementclass->flags & ACC_INTERFACE) {
                 /* We are assigning to an interface type. */
@@ -602,7 +777,7 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
         /* {value and dest.cls have the same dimension} */
 
         if (value->elementtype != arraydesc->elementtype)
-            return false;
+            return typecheck_FALSE;
 
         if (value->elementclass.any) {
             /* We are assigning an array of objects so we have to
@@ -618,10 +793,10 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
             }
             
             /* We are assigning to a class type. */
-            return class_issubclass(value->elementclass.cls,elementclass);
+            return merged_is_subclass(value->elementclass.cls,value->merged,elementclass);
         }
 
-        return true;
+        return typecheck_TRUE;
     }
 
     /* {dest.cls is not an array} */
@@ -635,14 +810,41 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
                int i = value->merged->count;
                while (i--)
                        if (IS_CLASSREF(*mlist++))
-                               return MAYBE;
+                               return typecheck_MAYBE;
        }
         
     /* We are assigning to a class type */
     if (cls->flags & ACC_INTERFACE)
         cls = class_java_lang_Object;
     
-    return class_issubclass(cls,dest.cls);
+    return merged_is_subclass(cls,value->merged,dest.cls);
+}
+
+/* typeinfo_is_assignable ******************************************************
+   Check if a type is assignable to a given type.
+   
+   IN:
+       value............the type of the value
+          dest.............the type of the destination, must not be a merged type
+
+   RETURN VALUE:
+       typecheck_TRUE...the type is assignable
+          typecheck_FALSE..the type is not assignable
+          typecheck_MAYBE..check cannot be performed now because of unresolved
+                           classes
+          typecheck_FAIL...an exception has been thrown
+
+*******************************************************************************/
+
+typecheck_result
+typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
+{
+       TYPEINFO_ASSERT(value);
+       TYPEINFO_ASSERT(dest);
+       TYPEINFO_ASSERT(dest->merged == NULL);
+
+       return typeinfo_is_assignable_to_class(value,dest->typeclass);
 }
 
 /**********************************************************************/
@@ -650,6 +852,57 @@ typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
 /* The following functions fill in uninitialized typeinfo structures. */
 /**********************************************************************/
 
+/* typeinfo_init_classinfo *****************************************************
+   Initialize a typeinfo to a resolved class.
+   
+   IN:
+          c................the class
+
+   OUT:
+       *info............is initialized
+
+   RETURN VALUE:
+       true.............success
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+void
+typeinfo_init_classinfo(typeinfo *info, classinfo *c)
+{
+       if ((info->typeclass.cls = c)->vftbl->arraydesc) {
+               if (c->vftbl->arraydesc->elementvftbl)
+                       info->elementclass.cls = c->vftbl->arraydesc->elementvftbl->class;
+               else
+                       info->elementclass.any = NULL;
+               info->dimension = c->vftbl->arraydesc->dimension;
+               info->elementtype = c->vftbl->arraydesc->elementtype;
+       }
+       else {
+               info->elementclass.any = NULL;
+               info->dimension = 0;
+               info->elementtype = 0;
+       }
+       info->merged = NULL;
+}
+
+/* typeinfo_init_class *********************************************************
+   Initialize a typeinfo to a possibly unresolved class type.
+   
+   IN:
+          c................the class type
+
+   OUT:
+       *info............is initialized
+
+   RETURN VALUE:
+       true.............success
+          false............an exception has been thrown
+
+*******************************************************************************/
+
 bool
 typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
 {
@@ -661,15 +914,14 @@ typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
        TYPEINFO_ASSERT(info);
 
        /* if necessary, try to resolve lazily */
-       if (!resolve_classref_or_classinfo(NULL /* XXX should now method */,
-                               c,resolveLazy,true,&cls))
+       if (!resolve_classref_or_classinfo(NULL /* XXX should know method */,
+                               c,resolveLazy,false,true,&cls))
        {
-               panic("XXX could not resolve class reference"); /* XXX */
                return false;
        }
        
        if (cls) {
-               TYPEINFO_INIT_CLASSINFO(*info,cls);
+               typeinfo_init_classinfo(info,cls);
                return true;
        }
 
@@ -705,7 +957,24 @@ typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
        return true;
 }
 
-void
+/* typeinfo_init_from_typedesc *************************************************
+   Initialize a typeinfo from a typedesc.
+   
+   IN:
+          desc.............the typedesc
+
+   OUT:
+       *type............set to the TYPE_* constant of DESC (if type != NULL)
+       *info............receives the typeinfo (if info != NULL)
+
+   RETURN VALUE:
+       true.............success
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
 typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
 {
        TYPEINFO_ASSERT(desc);
@@ -722,16 +991,49 @@ typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
        if (info) {
                if (desc->type == TYPE_ADR) {
                        TYPEINFO_ASSERT(desc->classref);
-                       TYPEINFO_INIT_CLASSREF(*info,desc->classref);
+                       if (!typeinfo_init_class(info,CLASSREF_OR_CLASSINFO(desc->classref)))
+                               return false;
                }
                else {
                        TYPEINFO_INIT_PRIMITIVE(*info);
                }
        }
+       return true;
 }
 
-void
-typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
+/* typeinfos_init_from_methoddesc **********************************************
+   Initialize an array of typeinfos and u1 TYPE_* values from a methoddesc.
+   
+   IN:
+       desc.............the methoddesc
+       buflen...........number of parameters the buffer can hold
+       twoword..........if true, use two parameter slots for two-word types
+
+   OUT:
+       *typebuf.........receives a TYPE_* constant for each parameter
+                        typebuf must be != NULL
+       *infobuf.........receives a typeinfo for each parameter
+                        infobuf must be != NULL
+       *returntype......receives a TYPE_* constant for the return type
+                        returntype may be NULL
+       *returntypeinfo..receives a typeinfo for the return type
+                        returntypeinfo may be NULL
+
+   RETURN VALUE:
+       true.............success
+       false............an exception has been thrown
+
+   NOTE:
+       If (according to BUFLEN) the buffers are to small to hold the
+          parameter types, an internal error is thrown. This must be
+          avoided by checking the number of parameters and allocating enough
+          space before calling this function.
+
+*******************************************************************************/
+
+bool
+typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
                               int buflen,bool twoword,
                               u1 *returntype,typeinfo *returntypeinfo)
 {
@@ -743,21 +1045,27 @@ typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
        TYPEINFO_ASSERT(infobuf);
 
 #ifdef TYPEINFO_VERBOSE
-       fprintf(stderr,"typeinfo_init_from_methoddesc(");
+       fprintf(stderr,"typeinfos_init_from_methoddesc(");
        descriptor_debug_print_methoddesc(stderr,desc);
        fprintf(stderr,")\n");
 #endif
 
     /* check arguments */
     for (i=0; i<desc->paramcount; ++i) {
-               if (++args > buflen)
-                       panic("Buffer too small for method arguments."); /* XXX */
+               if (++args > buflen) {
+                       exceptions_throw_internalerror("Buffer too small for method arguments.");
+                       return false;
+               }
 
-               typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++);
+               if (!typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++))
+                       return false;
                
-               if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) {
-                       if (++args > buflen)
-                               panic("Buffer too small for method arguments."); /* XXX */
+               if (twoword && (typebuf[-1] == TYPE_LNG || typebuf[-1] == TYPE_DBL)) {
+                       if (++args > buflen) {
+                               exceptions_throw_internalerror("Buffer too small for method arguments.");
+                               return false;
+                       }
+
                        *typebuf++ = TYPE_VOID;
                        TYPEINFO_INIT_PRIMITIVE(*infobuf);
                        infobuf++;
@@ -766,93 +1074,325 @@ typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
 
     /* check returntype */
     if (returntype) {
-               typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo);
+               if (!typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo))
+                       return false;
        }
+
+       return true;
 }
 
-void
+/* typedescriptor_init_from_typedesc *******************************************
+   Initialize a typedescriptor from a typedesc.
+   
+   IN:
+          desc.............the typedesc
+
+   OUT:
+       *td..............receives the typedescriptor
+                           td must be != NULL
+
+   RETURN VALUE:
+       true.............success
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
 typedescriptor_init_from_typedesc(typedescriptor *td,
                                                                  typedesc *desc)
 {
+       TYPEINFO_ASSERT(td);
+       TYPEINFO_ASSERT(desc);
+
        td->type = desc->type;
        if (td->type == TYPE_ADR) {
-               TYPEINFO_INIT_CLASSREF(td->info,desc->classref);
+               if (!typeinfo_init_class(&(td->typeinfo),CLASSREF_OR_CLASSINFO(desc->classref)))
+                       return false;
+       }
+       else {
+               TYPEINFO_INIT_PRIMITIVE(td->typeinfo);
+       }
+       return true;
+}
+
+/* typeinfo_init_varinfo_from_typedesc *****************************************
+   Initialize a varinfo from a typedesc.
+   
+   IN:
+          desc.............the typedesc
+
+   OUT:
+       *var.............receives the type
+                           var must be != NULL
+
+   RETURN VALUE:
+       true.............success
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
+typeinfo_init_varinfo_from_typedesc(varinfo *var,
+                                                                 typedesc *desc)
+{
+       TYPEINFO_ASSERT(var);
+       TYPEINFO_ASSERT(desc);
+
+       var->type = desc->type;
+       if (var->type == TYPE_ADR) {
+               if (!typeinfo_init_class(&(var->typeinfo),CLASSREF_OR_CLASSINFO(desc->classref)))
+                       return false;
        }
        else {
-               TYPEINFO_INIT_PRIMITIVE(td->info);
+               TYPEINFO_INIT_PRIMITIVE(var->typeinfo);
+       }
+       return true;
+}
+
+/* typeinfo_init_varinfos_from_methoddesc **************************************
+   Initialize an array of varinfos from a methoddesc.
+   
+   IN:
+       desc.............the methoddesc
+       buflen...........number of parameters the buffer can hold
+          startindex.......the zero-based index of the first parameter to
+                           write to the array. In other words the number of
+                                               parameters to skip at the beginning of the methoddesc.
+          map..............map from parameter indices to varinfo indices
+                           (indexed like jitdata.local_map)
+
+   OUT:
+       *vars............array receiving the varinfos
+                           td[0] receives the type of the
+                                               (startindex+1)th parameter of the method
+       *returntype......receives the typedescriptor of the return type.
+                           returntype may be NULL
+
+   RETURN VALUE:
+       true.............everything ok
+          false............an exception has been thrown
+
+   NOTE:
+       If (according to BUFLEN) the buffer is to small to hold the
+          parameter types, an internal error is thrown. This must be
+          avoided by checking the number of parameters and allocating enough
+          space before calling this function.
+
+*******************************************************************************/
+
+bool
+typeinfo_init_varinfos_from_methoddesc(varinfo *vars,
+                                                                        methoddesc *desc,
+                                                                        int buflen, int startindex,
+                                                                        s4 *map,
+                                                                        typedescriptor *returntype)
+{
+       s4 i;
+    s4 varindex;
+       s4 type;
+       s4 slot = 0;
+
+       /* skip arguments */
+       for (i=0; i<startindex; ++i) {
+               slot++;
+               if (IS_2_WORD_TYPE(desc->paramtypes[i].type))
+                       slot++;
+       }
+
+    /* check arguments */
+    for (i=startindex; i<desc->paramcount; ++i) {
+               type = desc->paramtypes[i].type;
+               varindex = map[5*slot + type];
+
+               slot++;
+               if (IS_2_WORD_TYPE(type))
+                       slot++;
+
+               if (varindex == UNUSED)
+                       continue;
+
+               if (varindex >= buflen) {
+                       exceptions_throw_internalerror("Buffer too small for method arguments.");
+                       return false;
+               }
+
+               if (!typeinfo_init_varinfo_from_typedesc(vars + varindex, desc->paramtypes + i))
+                       return false;
+    }
+
+    /* check returntype */
+    if (returntype) {
+               if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
+                       return false;
        }
+
+       return true;
 }
 
+/* typedescriptors_init_from_methoddesc ****************************************
+   Initialize an array of typedescriptors from a methoddesc.
+   
+   IN:
+       desc.............the methoddesc
+       buflen...........number of parameters the buffer can hold
+       twoword..........if true, use two parameter slots for two-word types
+          startindex.......the zero-based index of the first parameter to
+                           write to the array. In other words the number of
+                                               parameters to skip at the beginning of the methoddesc.
+
+   OUT:
+       *td..............array receiving the typedescriptors.
+                           td[0] receives the typedescriptor of the
+                                               (startindex+1)th parameter of the method
+       *returntype......receives the typedescriptor of the return type.
+                           returntype may be NULL
+
+   RETURN VALUE:
+       >= 0.............number of typedescriptors filled in TD
+          -1...............an exception has been thrown
+
+   NOTE:
+       If (according to BUFLEN) the buffer is to small to hold the
+          parameter types, an internal error is thrown. This must be
+          avoided by checking the number of parameters and allocating enough
+          space before calling this function.
+
+*******************************************************************************/
+
 int
 typedescriptors_init_from_methoddesc(typedescriptor *td,
                                                                         methoddesc *desc,
-                                                                        int buflen,bool twoword,
+                                                                        int buflen,bool twoword,int startindex,
                                                                         typedescriptor *returntype)
 {
        int i;
     int args = 0;
 
     /* check arguments */
-    for (i=0; i<desc->paramcount; ++i) {
-               if (++args > buflen)
-                       panic("Buffer too small for method arguments."); /* XXX */
+    for (i=startindex; i<desc->paramcount; ++i) {
+               if (++args > buflen) {
+                       exceptions_throw_internalerror("Buffer too small for method arguments.");
+                       return -1;
+               }
 
-               typedescriptor_init_from_typedesc(td,desc->paramtypes + i);
+               if (!typedescriptor_init_from_typedesc(td,desc->paramtypes + i))
+                       return -1;
                td++;
 
-               if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
-                       if (++args > buflen)
-                               panic("Buffer too small for method arguments."); /* XXX */
+               if (twoword && (td[-1].type == TYPE_LNG || td[-1].type == TYPE_DBL)) {
+                       if (++args > buflen) {
+                               exceptions_throw_internalerror("Buffer too small for method arguments.");
+                               return -1;
+                       }
+
                        td->type = TYPE_VOID;
-                       TYPEINFO_INIT_PRIMITIVE(td->info);
+                       TYPEINFO_INIT_PRIMITIVE(td->typeinfo);
                        td++;
                }
     }
 
     /* check returntype */
     if (returntype) {
-               typedescriptor_init_from_typedesc(returntype,&(desc->returntype));
+               if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
+                       return -1;
        }
 
        return args;
 }
 
-void
+/* typeinfo_init_component *****************************************************
+   Initialize a typeinfo with the component type of a given array type.
+   
+   IN:
+          srcarray.........the typeinfo of the array type
+
+   OUT:
+       *dst.............receives the typeinfo of the component type
+
+   RETURN VALUE:
+       true.............success
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
 {
+       typeinfo_mergedlist *merged;
+
+       TYPEINFO_ASSERT(srcarray);
+       TYPEINFO_ASSERT(dst);
+
     if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
         TYPEINFO_INIT_NULLTYPE(*dst);
-        return;
+        return true;
     }
     
-    if (!TYPEINFO_IS_ARRAY(*srcarray))
-        panic("Trying to access component of non-array"); /* XXX throw exception */
+    if (!TYPEINFO_IS_ARRAY(*srcarray)) {
+               /* XXX should we make that a verify error? */
+               exceptions_throw_internalerror("Trying to access component of non-array");
+               return false;
+       }
+
+       /* save the mergedlist (maybe dst == srcarray) */
+
+       merged = srcarray->merged;
 
        if (IS_CLASSREF(srcarray->typeclass)) {
                constant_classref *comp;
                comp = class_get_classref_component_of(srcarray->typeclass.ref);
 
-               if (comp)
-                       TYPEINFO_INIT_CLASSREF(*dst,comp);
-               else
+               if (comp) {
+                       if (!typeinfo_init_class(dst,CLASSREF_OR_CLASSINFO(comp)))
+                               return false;
+               }
+               else {
                        TYPEINFO_INIT_PRIMITIVE(*dst);
+               }
        }
        else {
                vftbl_t *comp;
+               
+               if (!(srcarray->typeclass.cls->state & CLASS_LINKED)) {
+                       if (!link_class(srcarray->typeclass.cls)) {
+                               return false;
+                       }
+               }
 
                TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl);
                TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl->arraydesc);
 
                comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl;
                if (comp)
-                       TYPEINFO_INIT_CLASSINFO(*dst,comp->class);
+                       typeinfo_init_classinfo(dst,comp->class);
                else
                        TYPEINFO_INIT_PRIMITIVE(*dst);
        }
     
-    dst->merged = srcarray->merged; /* XXX should we do a deep copy? */
+    dst->merged = merged; /* XXX should we do a deep copy? */
+       return true;
 }
 
+/* typeinfo_clone **************************************************************
+   Create a deep copy of a typeinfo struct.
+   
+   IN:
+          src..............the typeinfo to copy
+
+   OUT:
+       *dest............receives the copy
+
+   NOTE:
+       If src == dest this function is a nop.
+
+*******************************************************************************/
+
 void
 typeinfo_clone(typeinfo *src,typeinfo *dest)
 {
@@ -880,6 +1420,16 @@ typeinfo_clone(typeinfo *src,typeinfo *dest)
 /* MISCELLANEOUS FUNCTIONS                                            */
 /**********************************************************************/
 
+/* typeinfo_free ***************************************************************
+   Free memory referenced by the given typeinfo. The typeinfo itself is not
+   freed.
+   
+   IN:
+       info.............the typeinfo
+
+*******************************************************************************/
+
 void
 typeinfo_free(typeinfo *info)
 {
@@ -895,15 +1445,17 @@ typeinfo_free(typeinfo *info)
 
 static
 void
-typeinfo_merge_error(char *str,typeinfo *x,typeinfo *y) {
+typeinfo_merge_error(methodinfo *m,char *str,typeinfo *x,typeinfo *y) {
 #ifdef TYPEINFO_VERBOSE
     fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
     fprintf(stderr,"Typeinfo x:\n");
     typeinfo_print(stderr,x,1);
     fprintf(stderr,"Typeinfo y:\n");
     typeinfo_print(stderr,y,1);
+    log_text(str);
 #endif
-    panic(str); /* XXX throw an exception */
+
+       exceptions_throw_verifyerror(m, str);
 }
 
 /* Condition: clsx != clsy. */
@@ -912,6 +1464,7 @@ static
 bool
 typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
 {
+       TYPEINFO_ASSERT(dest);
     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
     TYPEINFO_ALLOCMERGED(dest->merged,2);
     dest->merged->count = 2;
@@ -1088,8 +1641,32 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
     return true;
 }
 
-static
-bool
+/* typeinfo_merge_nonarrays ****************************************************
+   Merge two non-array types.
+   
+   IN:
+       x................the first type
+          y................the second type
+          mergedx..........merged list of the first type, may be NULL
+          mergedy..........merged list of the descond type, may be NULL
+
+   OUT:
+       *dest............receives the resulting merged list
+          *result..........receives the resulting type
+
+   RETURN VALUE:
+       typecheck_TRUE...*dest has been modified
+          typecheck_FALSE..*dest has not been modified
+          typecheck_FAIL...an exception has been thrown
+
+   NOTE:
+       RESULT is an extra parameter so it can point to dest->typeclass or to
+          dest->elementclass.
+
+*******************************************************************************/
+
+static typecheck_result
 typeinfo_merge_nonarrays(typeinfo *dest,
                          classref_or_classinfo *result,
                          classref_or_classinfo x,classref_or_classinfo y,
@@ -1100,6 +1677,7 @@ typeinfo_merge_nonarrays(typeinfo *dest,
     classinfo *tcls,*common;
     typeinfo_mergedlist *tmerged;
     bool changed;
+       typecheck_result r;
        utf *xname;
        utf *yname;
 
@@ -1109,26 +1687,6 @@ typeinfo_merge_nonarrays(typeinfo *dest,
        TYPEINFO_ASSERT(x.cls != pseudo_class_New);
        TYPEINFO_ASSERT(y.cls != pseudo_class_New);
 
-#ifdef XXX
-       /* check clsx */
-       if (!clsx->loaded)
-               if (!load_class_bootstrap(clsx))
-                       return false;
-
-       if (!clsx->linked)
-               if (!link_class(clsx))
-                       return false;
-
-       /* check clsy */
-       if (!clsy->loaded)
-               if (!load_class_bootstrap(clsy))
-                       return false;
-
-       if (!clsy->linked)
-               if (!link_class(clsy))
-                       return false;
-#endif
-
        /*--------------------------------------------------*/
        /* common cases                                     */
        /*--------------------------------------------------*/
@@ -1168,9 +1726,12 @@ typeinfo_merge_nonarrays(typeinfo *dest,
        {
                typeinfo dbgx,dbgy;
                fprintf(stderr,"merge_nonarrays:\n");
-               TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgx,x);
+               fprintf(stderr,"    ");if(IS_CLASSREF(x))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,xname);fprintf(stderr,"\n");
+               fprintf(stderr,"    ");if(IS_CLASSREF(y))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,yname);fprintf(stderr,"\n");
+               fflush(stderr);
+               typeinfo_init_class(&dbgx,x);
                dbgx.merged = mergedx;
-               TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgy,y);
+               typeinfo_init_class(&dbgy,y);
                dbgy.merged = mergedy;
                typeinfo_print(stderr,&dbgx,4);
                fprintf(stderr,"  with:\n");
@@ -1178,6 +1739,9 @@ typeinfo_merge_nonarrays(typeinfo *dest,
        }
 #endif
 
+       TYPEINFO_ASSERT(IS_CLASSREF(x) || (x.cls->state & CLASS_LOADED));
+       TYPEINFO_ASSERT(IS_CLASSREF(y) || (y.cls->state & CLASS_LOADED));
+
     /* If y is unresolved or an interface, swap x and y. */
     if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE))
        {
@@ -1204,6 +1768,10 @@ typeinfo_merge_nonarrays(typeinfo *dest,
        /* {We know: both x and y are resolved} */
     /* {We know: If only one of x,y is an interface it is x.} */
 
+       TYPEINFO_ASSERT(!IS_CLASSREF(x) && !IS_CLASSREF(y));
+       TYPEINFO_ASSERT(x.cls->state & CLASS_LOADED);
+       TYPEINFO_ASSERT(y.cls->state & CLASS_LOADED);
+
     /* Handle merging of interfaces: */
     if (x.cls->flags & ACC_INTERFACE) {
         /* {x.cls is an interface and mergedx == NULL.} */
@@ -1224,34 +1792,57 @@ typeinfo_merge_nonarrays(typeinfo *dest,
             x = y;
             goto return_simple_x;
         }
-            
 
         /* If the type y implements x then the result of the merge
          * is x regardless of mergedy.
          */
+
+               /* we may have to link the classes */
+               if (!(x.cls->state & CLASS_LINKED))
+                       if (!link_class(x.cls))
+                               return typecheck_FAIL;
+               if (!(y.cls->state & CLASS_LINKED))
+                       if (!link_class(y.cls))
+                               return typecheck_FAIL;
         
-        if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index)
-            || mergedlist_implements_interface(mergedy,x.cls))
+               TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
+               TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
+
+        if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index))
+               {
+            /* y implements x, so the result of the merge is x. */
+            goto return_simple_x;
+               }
+               
+        r = mergedlist_implements_interface(mergedy,x.cls);
+               if (r == typecheck_FAIL)
+                       return r;
+               if (r == typecheck_TRUE)
         {
             /* y implements x, so the result of the merge is x. */
             goto return_simple_x;
         }
         
         /* {We know: x is an interface, the type y a class or a merge
-         * of subclasses and does not implement x.} */
+         * of subclasses and is not guaranteed to implement x.} */
 
-        /* There may still be superinterfaces of x which are implemented
-         * by y, too, so we have to add x.cls to the mergedlist.
-         */
-
-        /* if x has no superinterfaces we could return a simple java.lang.Object */
-        
         common = class_java_lang_Object;
         goto merge_with_simple_x;
     }
 
     /* {We know: x and y are classes (not interfaces).} */
     
+       /* we may have to link the classes */
+       if (!(x.cls->state & CLASS_LINKED))
+               if (!link_class(x.cls))
+                       return typecheck_FAIL;
+       if (!(y.cls->state & CLASS_LINKED))
+               if (!link_class(y.cls))
+                       return typecheck_FAIL;
+        
+       TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
+       TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
+
     /* If *x is deeper in the inheritance hierarchy swap x and y. */
     if (x.cls->index > y.cls->index) {
         t = x; x = y; y = t;
@@ -1264,10 +1855,10 @@ typeinfo_merge_nonarrays(typeinfo *dest,
     common = x.cls;
     tcls = y.cls;
     while (tcls->index > common->index)
-        tcls = tcls->super;
+        tcls = tcls->super.cls;
     while (common != tcls) {
-        common = common->super;
-        tcls = tcls->super;
+        common = common->super.cls;
+        tcls = tcls->super.cls;
     }
 
     /* {common == nearest common anchestor of x and y.} */
@@ -1295,11 +1886,31 @@ merge_with_simple_x:
         return typeinfo_merge_two(dest,x,y);
 }
 
-/* Condition: *dest must be a valid initialized typeinfo. */
-/* Condition: dest != y. */
-/* Returns: true if dest was changed. */
-bool
-typeinfo_merge(typeinfo *dest,typeinfo* y)
+/* typeinfo_merge **************************************************************
+   Merge two types.
+   
+   IN:
+       m................method for exception messages
+       dest.............the first type
+       y................the second type
+
+   OUT:
+       *dest............receives the result of the merge
+
+   RETURN VALUE:
+       typecheck_TRUE...*dest has been modified
+       typecheck_FALSE..*dest has not been modified
+       typecheck_FAIL...an exception has been thrown
+
+   PRE-CONDITIONS:
+       1) *dest must be a valid initialized typeinfo
+       2) dest != y
+
+*******************************************************************************/
+
+typecheck_result
+typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y)
 {
     typeinfo *x;
     typeinfo *tmp;
@@ -1308,6 +1919,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
     int dimension;
     int elementtype;
     bool changed;
+       typecheck_result r;
 
        /*--------------------------------------------------*/
        /* fast checks                                      */
@@ -1315,7 +1927,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
 
     /* Merging something with itself is a nop */
     if (dest == y)
-        return false;
+        return typecheck_FALSE;
 
     /* Merging two returnAddress types is ok. */
        /* Merging two different returnAddresses never happens, as the verifier */
@@ -1323,22 +1935,25 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
        /* from JSR subroutines.                                                */
     if (!dest->typeclass.any && !y->typeclass.any) {
                TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) ==  TYPEINFO_RETURNADDRESS(*y));
-        return false;
+        return typecheck_FALSE;
        }
     
     /* Primitive types cannot be merged with reference types */
-       /* XXX only check this in debug mode? */
-    if (!dest->typeclass.any || !y->typeclass.any)
-        typeinfo_merge_error("Trying to merge primitive types.",dest,y);
+       /* This must be checked before calls to typeinfo_merge.  */
+    TYPEINFO_ASSERT(dest->typeclass.any && y->typeclass.any);
 
     /* handle uninitialized object types */
     if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
-        if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y))
-            typeinfo_merge_error("Trying to merge uninitialized object type.",dest,y);
-        if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest)
-            != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
-            typeinfo_merge_error("Trying to merge different uninitialized objects.",dest,y);
-        return false;
+        if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y)) {
+            typeinfo_merge_error(m,"Trying to merge uninitialized object type.",dest,y);
+                       return typecheck_FAIL;
+               }
+        if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest) != TYPEINFO_NEWOBJECT_INSTRUCTION(*y)) {
+            typeinfo_merge_error(m,"Trying to merge different uninitialized objects.",dest,y);
+                       return typecheck_FAIL;
+               }
+               /* the same uninitialized object -- no change */
+               return typecheck_FALSE;
     }
     
        /*--------------------------------------------------*/
@@ -1359,12 +1974,12 @@ return_simple:
     
     /* Handle null types: */
     if (TYPEINFO_IS_NULLTYPE(*y)) {
-        return false;
+        return typecheck_FALSE;
     }
     if (TYPEINFO_IS_NULLTYPE(*dest)) {
         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
         TYPEINFO_CLONE(*y,*dest);
-        return true;
+        return typecheck_TRUE;
     }
 
        /* Common case: two types with the same name, at least one unresolved */
@@ -1434,7 +2049,12 @@ return_simple:
                 elementclass.any = NULL;
             }
             else {
-                common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub);
+                common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub,true);
+                               if (!common.cls) {
+                                       exceptions_throw_internalerror("XXX Coult not create array class");
+                                       return typecheck_FAIL;
+                               }
+
                 elementtype = ARRAYTYPE_OBJECT;
                 elementclass.cls = pseudo_class_Arraystub;
             }
@@ -1446,18 +2066,27 @@ return_simple:
                 /* The elements are references, so their respective
                  * types must be merged.
                  */
-                changed |= typeinfo_merge_nonarrays(dest,
-                                                    &elementclass,
-                                                    x->elementclass,
-                                                    elementclass,
-                                                    x->merged,y->merged);
+                               r = typeinfo_merge_nonarrays(dest,
+                                               &elementclass,
+                                               x->elementclass,
+                                               elementclass,
+                                               x->merged,y->merged);
+                               TYPEINFO_ASSERT(r != typecheck_MAYBE);
+                               if (r == typecheck_FAIL)
+                                       return r;
+                               changed |= r;
 
                 /* DEBUG */ /* log_text("finding resulting array class: "); */
                                if (IS_CLASSREF(elementclass))
                                        common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref);
-                               else
-                                       common.cls = class_multiarray_of(dimension,elementclass.cls);
-                /* DEBUG */ /* utf_display(common->name); printf("\n"); */
+                               else {
+                                       common.cls = class_multiarray_of(dimension,elementclass.cls,true);
+                                       if (!common.cls) {
+                                               exceptions_throw_internalerror("XXX Coult not create array class");
+                                               return typecheck_FAIL;
+                                       }
+                               }
+                /* DEBUG */ /* utf_display_printable_ascii(common->name); printf("\n"); */
             }
                        else {
                                common.any = y->typeclass.any;
@@ -1468,10 +2097,14 @@ return_simple:
         /* {We know that at least one of x or y is no array, so the
          *  result cannot be an array.} */
         
-        changed |= typeinfo_merge_nonarrays(dest,
-                                            &common,
-                                            x->typeclass,y->typeclass,
-                                            x->merged,y->merged);
+               r = typeinfo_merge_nonarrays(dest,
+                               &common,
+                               x->typeclass,y->typeclass,
+                               x->merged,y->merged);
+               TYPEINFO_ASSERT(r != typecheck_MAYBE);
+               if (r == typecheck_FAIL)
+                       return r;
+               changed |= r;
 
         dimension = 0;
         elementtype = 0;
@@ -1499,6 +2132,7 @@ return_simple:
 
     return changed;
 }
+#endif /* ENABLE_VERIFER */
 
 
 /**********************************************************************/
@@ -1507,6 +2141,7 @@ return_simple:
 
 #ifdef TYPEINFO_DEBUG
 
+#if 0
 static int
 typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
 {
@@ -1515,7 +2150,6 @@ typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
     return +1;
 }
 
-#if 0
 static void
 typeinfo_test_parse(typeinfo *info,char *str)
 {
@@ -1538,8 +2172,11 @@ typeinfo_test_parse(typeinfo *info,char *str)
         info->merged->count = num;
 
         for (i=0; i<num; ++i) {
-            if (typebuf[i] != TYPE_ADDRESS)
-                panic("non-reference type in mergedlist");
+            if (typebuf[i] != TYPE_ADR) {
+                log_text("non-reference type in mergedlist");
+                               assert(0);
+                       }
+
             info->merged->list[i].any = infobuf[i].typeclass.any;
         }
         qsort(info->merged->list,num,sizeof(classref_or_classinfo),
@@ -1586,6 +2223,7 @@ typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
 {
     typeinfo dest;
     bool changed,changed_should_be;
+       typecheck_result r;
 
     TYPEINFO_CLONE(*a,dest);
     
@@ -1595,7 +2233,12 @@ typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
     typeinfo_print_short(stdout,b);
     printf("\n");
 
-    changed = (typeinfo_merge(&dest,b)) ? 1 : 0;
+       r = typeinfo_merge(NULL,&dest,b);
+       if (r == typecheck_FAIL) {
+               printf("EXCEPTION\n");
+               return;
+       }
+    changed = (r) ? 1 : 0;
     changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
 
     printf("          %s\n",(changed) ? "changed" : "=");
@@ -1628,7 +2271,7 @@ typeinfo_inc_dimension(typeinfo *info)
         info->elementtype = ARRAYTYPE_OBJECT;
         info->elementclass = info->typeclass;
     }
-    info->typeclass = class_array_of(info->typeclass);
+    info->typeclass = class_array_of(info->typeclass,true);
 }
 #endif
 
@@ -1647,16 +2290,21 @@ typeinfo_testrun(char *filename)
     FILE *file = fopen(filename,"rt");
        int res;
     
-    if (!file)
-        panic("could not open typeinfo test file");
+    if (!file) {
+        log_text("could not open typeinfo test file");
+               assert(0);
+       }
 
     while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
         if (buf[0] == '#' || !strlen(buf))
             continue;
         
         res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
-        if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc))
-            panic("Invalid line in typeinfo test file (none of empty, comment or test)");
+        if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) {
+            log_text("Invalid line in typeinfo test file (none of empty, comment or test)");
+                       assert(0);
+               }
+
 #if 0
         typeinfo_test_parse(&a,bufa);
         typeinfo_test_parse(&b,bufb);
@@ -1690,7 +2338,8 @@ typeinfo_testrun(char *filename)
 
     if (failed) {
         fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
-        panic("Failed test");
+        log_text("Failed test");
+               assert(0);
     }
 }
 
@@ -1723,10 +2372,10 @@ typeinfo_print_class(FILE *file,classref_or_classinfo c)
        else {
                if (IS_CLASSREF(c)) {
                        fprintf(file,"<ref>");
-                       utf_fprint(file,c.ref->name);
+                       utf_fprint_printable_ascii(file,c.ref->name);
                }
                else {
-                       utf_fprint(file,c.cls->name);
+                       utf_fprint_printable_ascii(file,c.cls->name);
                }
        }
 }
@@ -1748,7 +2397,7 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
     if (TYPEINFO_IS_PRIMITIVE(*info)) {
                bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
                if (bptr)
-                       fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr);
+                       fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->nr);
                else
                        fprintf(file,"%sprimitive\n",ind);
         return;
@@ -1760,10 +2409,10 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
     }
 
     if (TYPEINFO_IS_NEWOBJECT(*info)) {
-        ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
+        ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
         if (ins) {
-            fprintf(file,"%sNEW(%p):",ind,ins);
-                       typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
+            fprintf(file,"%sNEW(%p):",ind,(void*)ins);
+                       typeinfo_print_class(file,ins[-1].sx.val.c);
             fprintf(file,"\n");
         }
         else {
@@ -1815,7 +2464,6 @@ typeinfo_print_short(FILE *file,typeinfo *info)
     int i;
     instruction *ins;
        basicblock *bptr;
-       classref_or_classinfo c;
 
        /*fprintf(file,"<typeinfo %p>",info);*/
 
@@ -1827,7 +2475,7 @@ typeinfo_print_short(FILE *file,typeinfo *info)
     if (TYPEINFO_IS_PRIMITIVE(*info)) {
                bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
                if (bptr)
-                       fprintf(file,"ret(L%03d)",bptr->debug_nr);
+                       fprintf(file,"ret(L%03d)",bptr->nr);
                else
                        fprintf(file,"primitive");
         return;
@@ -1839,11 +2487,11 @@ typeinfo_print_short(FILE *file,typeinfo *info)
     }
     
     if (TYPEINFO_IS_NEWOBJECT(*info)) {
-        ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
+        ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
         if (ins) {
                        /*fprintf(file,"<ins %p>",ins);*/
-            fprintf(file,"NEW(%p):",ins);
-                       typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
+            fprintf(file,"NEW(%p):",(void*)ins);
+                       typeinfo_print_class(file,ins[-1].sx.val.c);
         }
         else
             fprintf(file,"NEW(this)");
@@ -1866,12 +2514,13 @@ void
 typeinfo_print_type(FILE *file,int type,typeinfo *info)
 {
     switch (type) {
-      case TYPE_VOID:   fprintf(file,"V"); break;
-      case TYPE_INT:    fprintf(file,"I"); break;
-      case TYPE_FLOAT:  fprintf(file,"F"); break;
-      case TYPE_DOUBLE: fprintf(file,"D"); break;
-      case TYPE_LONG:   fprintf(file,"J"); break;
-      case TYPE_ADDRESS:
+      case TYPE_VOID: fprintf(file,"V"); break;
+      case TYPE_INT:  fprintf(file,"I"); break;
+      case TYPE_FLT:  fprintf(file,"F"); break;
+      case TYPE_DBL:  fprintf(file,"D"); break;
+      case TYPE_LNG:  fprintf(file,"J"); break;
+         case TYPE_RET:  fprintf(file,"R:"); /* FALLTHROUGH! */
+      case TYPE_ADR:
                  typeinfo_print_short(file,info);
           break;
           
@@ -1880,67 +2529,20 @@ typeinfo_print_type(FILE *file,int type,typeinfo *info)
     }
 }
 
-void
-typeinfo_print_stacktype(FILE *file,int type,typeinfo *info)
-{
-       TYPEINFO_ASSERT(file);
-       TYPEINFO_ASSERT(type != TYPE_ADDRESS || info != NULL);
-       if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) {     
-               typeinfo_retaddr_set *set = (typeinfo_retaddr_set*)
-                       TYPEINFO_RETURNADDRESS(*info);
-               fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr);
-               set = set->alt;
-               while (set) {
-                       fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr);
-                       set = set->alt;
-               }
-               fprintf(file,")");
-       }
-       else
-               typeinfo_print_type(file,type,info);
-}
-
 void
 typedescriptor_print(FILE *file,typedescriptor *td)
 {
-       typeinfo_print_type(file,td->type,&(td->info));
+       typeinfo_print_type(file,td->type,&(td->typeinfo));
 }
 
 void
-typevector_print(FILE *file,typevector *vec,int size)
+typevector_print(FILE *file,varinfo *vec,int size)
 {
     int i;
 
-       fprintf(file,"[%d]",vec->k);
     for (i=0; i<size; ++i) {
                fprintf(file," %d=",i);
-        typedescriptor_print(file,vec->td + i);
-    }
-}
-
-void
-typevectorset_print(FILE *file,typevector *set,int size)
-{
-    int i;
-       typevector *vec;
-
-       fprintf(file,"[%d",set->k);
-       vec = set->alt;
-       while (vec) {
-               fprintf(file,"|%d",vec->k);
-               vec = vec->alt;
-       }
-       fprintf(file,"]");
-       
-    for (i=0; i<size; ++i) {
-               fprintf(file," %d=",i);
-        typedescriptor_print(file,set->td + i);
-               vec = set->alt;
-               while (vec) {
-                       fprintf(file,"|");
-                       typedescriptor_print(file,vec->td + i);
-                       vec = vec->alt;
-               }
+        typeinfo_print_type(file, vec[i].type, &(vec[i].typeinfo));
     }
 }
 
@@ -1958,4 +2560,5 @@ typevectorset_print(FILE *file,typevector *set,int size)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */