extended type system to use symbolic references
authoredwin <none@none>
Fri, 1 Apr 2005 16:53:33 +0000 (16:53 +0000)
committeredwin <none@none>
Fri, 1 Apr 2005 16:53:33 +0000 (16:53 +0000)
introduce pre-parsed descriptors
cleaned up headers
made classcache thread-safe

33 files changed:
src/vm/Makefile.am
src/vm/access.h
src/vm/class.c
src/vm/class.h
src/vm/classcache.c
src/vm/classcache.h
src/vm/descriptor.c
src/vm/descriptor.h
src/vm/exceptions.h
src/vm/field.h
src/vm/global.h
src/vm/jit/codegen.inc.h
src/vm/jit/inline/parseXTA.h
src/vm/jit/inline/sets.c
src/vm/jit/inline/sets.h
src/vm/jit/jit.h
src/vm/jit/stack.c
src/vm/jit/stack.h
src/vm/jit/tools/genoffsets.c
src/vm/jit/verify/typecheck.c
src/vm/jit/verify/typeinfo.c
src/vm/jit/verify/typeinfo.h
src/vm/linker.c
src/vm/linker.h
src/vm/loader.c
src/vm/loader.h
src/vm/method.c
src/vm/method.h
src/vm/references.h [new file with mode: 0644]
src/vm/resolve.c
src/vm/resolve.h
src/vm/stringlocal.h
src/vm/utf8.h

index 3c400fb7d5a763d58254e7d02b4473541c1dbcb6..58ef7b48281cc195d968c09fade02ce3d76e0a90 100644 (file)
@@ -28,7 +28,7 @@
 ##
 ## Changes:
 ##
-## $Id: Makefile.am 2130 2005-03-29 22:30:51Z twisti $
+## $Id: Makefile.am 2181 2005-04-01 16:53:33Z edwin $
 
 ## Process this file with automake to produce Makefile.in
 
@@ -75,6 +75,7 @@ libvmcore_la_SOURCES = \
        method.h \
        options.c \
        options.h \
+       references.h \
        resolve.c \
        resolve.h \
        $(STATISTICS_OBJ) \
index fb66db99b00c4ced73edccfb49d3fbf859280c29..7eadfc2310b36a2b99ef5a0845eaba96fb6b2a5e 100644 (file)
 
    Changes:
 
-   $Id: access.h 2111 2005-03-29 21:28:24Z twisti $
+   $Id: access.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 #ifndef _ACCESS_H
 #define _ACCESS_H
 
-#include "types.h"
-#include "vm/class.h"
+#include "vm/references.h"
 
 
 /* macros *********************************************************************/
index 5995c1ec9f49a3d023abd1c4c179bf1d07ce324d..23193e2d64b975c136f6186076db285fdedc2f6c 100644 (file)
             Andreas Krall
             Christian Thalinger
 
-   $Id: class.c 2153 2005-03-30 19:30:05Z twisti $
+   $Id: class.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 #include <assert.h>
 #include <string.h>
 
-#include "config.h"
-#include "types.h"
-
+#include "vm/global.h"
 #include "mm/memory.h"
 
 #if defined(USE_THREADS)
@@ -58,6 +56,7 @@
 #include "vm/statistics.h"
 #include "vm/tables.h"
 #include "vm/utf8.h"
+#include "vm/loader.h"
 
 
 /******************************************************************************/
index ddc104f7a0acb839dee92c59fc4d6059987f46a9..cdd22692e7995c600551b5602a56ec5e631db160 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: class.h 2153 2005-03-30 19:30:05Z twisti $
+   $Id: class.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 
 /* forward typedefs ***********************************************************/
 
-typedef struct classinfo classinfo; 
 typedef struct innerclassinfo innerclassinfo;
-typedef struct constant_classref constant_classref;
 typedef struct extra_classref extra_classref;
 
-
 #include "config.h"
 #include "toolbox/list.h"
-#include "vm/field.h"
 #include "vm/global.h"
+#include "vm/utf8.h"
+#include "vm/references.h"
+#include "vm/field.h"
 #include "vm/linker.h"
 #include "vm/tables.h"
-#include "vm/utf8.h"
 #include "vm/jit/inline/sets.h"
 
-
 /* classinfo ******************************************************************/
 
 struct classinfo {                /* class structure                          */
@@ -135,15 +132,6 @@ struct innerclassinfo {
 };
 
 
-/* constant_classref **********************************************************/
-
-struct constant_classref {
-       vftbl_t   *pseudo_vftbl;      /* for distinguishing it from classinfo     */
-       classinfo *referer;           /* class containing the reference           */
-       utf       *name;              /* name of the class refered to             */
-};
-
-
 /* extra_classref **************************************************************
 
    for classrefs not occurring within descriptors
@@ -231,15 +219,6 @@ extern classinfo *pseudo_class_Null;
 extern classinfo *pseudo_class_New;
 
 
-/* macros *********************************************************************/
-
-/* initialize a constant_classref with referer `ref` and name `classname` */
-#define CLASSREF_INIT(c,ref,classname)                          \
-                       do { (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL;      \
-                                (c).referer = (ref);                           \
-                                (c).name = (classname); } while (0)
-
-
 /* function prototypes ********************************************************/
 
 void class_init_foo(void);
index 9737b7e1fb89145f468f4bf0fed6a5b76280df84..401ccb74579966b3c10e78cd3e32f4bfc2ccd620 100644 (file)
 
    Changes:
 
-   $Id: classcache.c 2083 2005-03-25 14:25:15Z edwin $
+   $Id: classcache.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 #include <assert.h>
 #include "vm/classcache.h"
-#include "vm/tables.h"
 #include "vm/utf8.h"
+#include "vm/tables.h"
 #include "vm/exceptions.h"
 #include "mm/memory.h"
 
 #define CLASSCACHE_ASSERT(cond)
 #endif
 
+/*============================================================================*/
+/* THREAD-SAFE LOCKING                                                        */
+/*============================================================================*/
+
+    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+    /* CAUTION: The static functions below are */
+    /*          NOT synchronized!              */
+    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+#  define CLASSCACHE_LOCK()    tables_lock()
+#  define CLASSCACHE_UNLOCK()  tables_unlock()
+#else
+#  define CLASSCACHE_LOCK()
+#  define CLASSCACHE_UNLOCK()
+#endif
+
 /*============================================================================*/
 /* GLOBAL VARIABLES                                                           */
 /*============================================================================*/
@@ -69,6 +86,8 @@ static hashtable classcache_hash;
 /* classcache_init *************************************************************
  
    Initialize the loaded class cache
+
+   Note: NOT synchronized!
   
 *******************************************************************************/
 
@@ -303,6 +322,8 @@ classcache_new_name(utf *name)
    RETURN VALUE:
        The return value is a pointer to the cached class object,
        or NULL, if the class is not in the cache.
+
+   Note: synchronized with global tablelock
    
 *******************************************************************************/
 
@@ -312,6 +333,9 @@ classcache_lookup(classloader *initloader,utf *classname)
        classcache_name_entry *en;
        classcache_class_entry *clsen;
        classcache_loader_entry *lden;
+       classinfo *cls = NULL;
+
+       CLASSCACHE_LOCK();
 
        en = classcache_lookup_name(classname);
        
@@ -323,14 +347,15 @@ classcache_lookup(classloader *initloader,utf *classname)
                                if (lden->loader == initloader) {
                                        /* found the loaded class entry */
                                        CLASSCACHE_ASSERT(clsen->classobj);
-                                       return clsen->classobj;
+                                       cls = clsen->classobj;
+                                       goto found;
                                }
                        }
                }
        }
-       
-       /* not found */
-       return NULL;
+found:
+       CLASSCACHE_UNLOCK();
+       return cls;
 }
 
 /* classcache_store ************************************************************
@@ -346,6 +371,8 @@ classcache_lookup(classloader *initloader,utf *classname)
                         the cache if necessary,
        false............an exception has been thrown.
    
+   Note: synchronized with global tablelock
+   
 *******************************************************************************/
 
 bool
@@ -357,7 +384,7 @@ classcache_store(classloader *initloader,classinfo *cls)
 
        CLASSCACHE_ASSERT(cls);
 
-       /* XXX lock table */
+       CLASSCACHE_LOCK();
 
        en = classcache_new_name(cls->name);
 
@@ -384,7 +411,7 @@ classcache_store(classloader *initloader,classinfo *cls)
                                        /* a loading constraint is violated */
                                        *exceptionptr = new_exception_message(string_java_lang_LinkageError,
                                                        "loading constraint violated XXX add message");
-                                       return false; /* exception */
+                                       goto return_exception;
                                }
 
                                /* record initloader as initiating loader */
@@ -394,7 +421,7 @@ classcache_store(classloader *initloader,classinfo *cls)
                                clsen->classobj = cls;
 
                                /* done */
-                               return true;
+                               goto return_success;
                        }
                }
                
@@ -411,8 +438,13 @@ classcache_store(classloader *initloader,classinfo *cls)
        clsen->next = en->classes;
        en->classes = clsen;
 
-       /* done */
+return_success:
+       CLASSCACHE_UNLOCK();
        return true;
+
+return_exception:
+       CLASSCACHE_UNLOCK();
+       return false; /* exception */
 }
 
 /* classcache_find_loader ******************************************************
@@ -552,6 +584,8 @@ classcache_free_name_entry(classcache_name_entry *entry)
        The class cache may not be used any more after this call, except
           when it is reinitialized with classcache_init.
   
+   Note: NOT synchronized!
+  
 *******************************************************************************/
 
 void 
@@ -590,6 +624,8 @@ classcache_free()
        true.............everything ok, the constraint has been added,
        false............an exception has been thrown.
    
+   Note: synchronized with global tablelock
+   
 *******************************************************************************/
 
 bool
@@ -611,7 +647,7 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname)
        if (a == b)
                return true;
 
-       /* XXX lock table */
+       CLASSCACHE_LOCK();
 
        en = classcache_new_name(classname);
 
@@ -626,14 +662,14 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname)
 
                /* if the entries are the same, the constraint is already recorded */
                if (clsenA == clsenB)
-                       return true;
+                       goto return_success;
 
                /* check if the entries can be merged */
                if (clsenA->classobj && clsenB->classobj && clsenA->classobj != clsenB->classobj) {
                        /* no, the constraint is violated */
                        *exceptionptr = new_exception_message(string_java_lang_LinkageError,
                                        "loading constraint violated XXX add message");
-                       return false; /* exception */
+                       goto return_exception;
                }
 
                /* yes, merge the entries */
@@ -680,8 +716,13 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname)
                }
        }
 
-       /* done */
+return_success:
+       CLASSCACHE_UNLOCK();
        return true;
+
+return_exception:
+       CLASSCACHE_UNLOCK();
+       return false; /* exception */
 }
 
 /*============================================================================*/
@@ -695,6 +736,8 @@ classcache_add_constraint(classloader *a,classloader *b,utf *classname)
    IN:
        file.............output stream
   
+   Note: synchronized with global tablelock
+   
 *******************************************************************************/
 
 void
@@ -705,6 +748,8 @@ classcache_debug_dump(FILE *file)
        classcache_loader_entry *lden;
        u4 slot;
 
+       CLASSCACHE_LOCK();
+
        fprintf(file,"\n=== [loaded class cache] =====================================\n\n");
        fprintf(file,"hash size   : %d\n",classcache_hash.size);
        fprintf(file,"hash entries: %d\n",classcache_hash.entries);
@@ -733,6 +778,8 @@ classcache_debug_dump(FILE *file)
                }
        }
        fprintf(file,"\n==============================================================\n\n");
+
+       CLASSCACHE_UNLOCK();
 }
 
 /*
index 2323e9632a2ea879ee58ebf9c49cbc8c14dfb10f..127e85bd8450f7aa5e75cc0921add15bb39bc08e 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: classcache.h 2111 2005-03-29 21:28:24Z twisti $
+   $Id: classcache.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -38,8 +38,7 @@
 
 #include <stdio.h>  /* for FILE */
 
-#include "vm/class.h"
-#include "vm/utf8.h"
+#include "vm/references.h"
 
 
 /* forward declarations *******************************************************/
index fdc5bc9aa06c9683148dca01527b013a6b788a11..adabb62874f792e3b2f42c3762f21f365df64cc2 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: descriptor.c 2111 2005-03-29 21:28:24Z twisti $
+   $Id: descriptor.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -348,6 +348,8 @@ descriptor_pool_add_class(descriptor_pool *pool,utf *name)
                *exceptionptr = new_classformaterror(pool->referer,"Invalid class name");
                return false; /* exception */
        }
+
+       /* XXX check maximum array dimension */
        
        c = DNEW(classref_hash_entry);
        c->name = name;
index c62d72e650414a35d3ea810335c652e4a33038e3..092b59fa7c3657f3891f7490054ac48b1b1b837f 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: descriptor.h 2112 2005-03-29 21:29:08Z twisti $
+   $Id: descriptor.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 /* forward typedefs ***********************************************************/
 
 typedef struct descriptor_pool descriptor_pool;
-typedef struct typedesc typedesc;
-typedef struct methoddesc methoddesc;
-typedef union parseddesc parseddesc;
 
-
-#include "types.h"
-#include "vm/class.h"
 #include "vm/global.h"
+#include "vm/references.h"
 #include "vm/tables.h"
-#include "vm/utf8.h"
-
 
 /* data structures ************************************************************/ 
 
@@ -110,12 +103,6 @@ struct methoddesc {
        typedesc           paramtypes[1]; /* parameter types, variable length!    */
 };
 
-union parseddesc {
-       typedesc          *fd;        /* parsed field descriptor                  */
-       methoddesc        *md;        /* parsed method descriptor                 */
-       void              *any;       /* used for simple test against NULL        */
-};
-
 
 /* function prototypes ********************************************************/
 
@@ -361,6 +348,48 @@ void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d);
 
 void descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file);
 
+/* macros for descriptor parsing **********************************************/
+
+/* XXX These should be moved to descriptor.c */
+
+/* SKIP_FIELDDESCRIPTOR:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * CAUTION: This macro does not check for an unexpected end of the
+ * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
+ */
+#define SKIP_FIELDDESCRIPTOR(utf_ptr)                                                  \
+       do { while (*(utf_ptr)=='[') (utf_ptr)++;                                       \
+               if (*(utf_ptr)++=='L')                                                                  \
+                       while(*(utf_ptr)++ != ';') /* skip */; } while(0)
+
+/* SKIP_FIELDDESCRIPTOR_SAFE:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * Input:
+ *     utf_ptr....points to first char of descriptor
+ *     end_ptr....points to first char after the end of the string
+ *     errorflag..must be initialized (to false) by the caller!
+ * Output:
+ *     utf_ptr....points to first char after the descriptor
+ *     errorflag..set to true if the string ended unexpectedly
+ */
+#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag)                   \
+       do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++;     \
+               if ((utf_ptr) == (end_ptr))                                                                             \
+                       (errorflag) = true;                                                                                     \
+               else                                                                                                                    \
+                       if (*(utf_ptr)++=='L') {                                                                        \
+                               while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';')    \
+                                       /* skip */;                                                                                     \
+                               if ((utf_ptr)[-1] != ';')                                                               \
+                                       (errorflag) = true; }} while(0)
+
+
 #endif /* _DESCRIPTOR_H */
 
 
index 8bb3ab5f5f1b4834bf4bd47436d7b3f8b9949ad3..73d183947548daf6ce5b3b5be35797729b460ed3 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Christian Thalinger
 
-   $Id: exceptions.h 2147 2005-03-30 16:47:35Z twisti $
+   $Id: exceptions.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 #define _EXCEPTIONS_H
 
 
-#include "config.h"
-
 #include "vm/global.h"
 #include "native/include/java_lang_String.h"
 #include "native/include/java_lang_Throwable.h"
 #include "vm/builtin.h"
-#include "vm/class.h"
+#include "vm/references.h"
+#include "vm/method.h"
 
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
index a871456da3a079d72111015968ea4d06cedf5e04..e5759e4d83b4670a6ceb3a2b549ab047416d21b9 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: field.h 2113 2005-03-29 21:36:28Z twisti $
+   $Id: field.h 2181 2005-04-01 16:53:33Z edwin $
 */
 
 
 typedef struct fieldinfo fieldinfo; 
 
 
-#include "types.h"
-#include "vm/class.h"
-#include "vm/descriptor.h"
 #include "vm/global.h"
 #include "vm/utf8.h"
+#include "vm/references.h"
+#include "vm/descriptor.h"
 #include "vm/jit/inline/parseXTA.h"
 
 
index 6ab163b96aadd0a969858c6700b7aac87e9cb35a..e0b5307586436686bb4bb2cd4bb668c3fa0ef310 100644 (file)
@@ -33,7 +33,7 @@
             Joseph Wenninger
             Christian Thalinger
 
-   $Id: global.h 2157 2005-03-30 20:05:55Z twisti $
+   $Id: global.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -293,46 +293,6 @@ struct java_objectarray {
 extern bool cacao_initializing;
 
 
-/* macros for descriptor parsing **********************************************/
-
-/* SKIP_FIELDDESCRIPTOR:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * CAUTION: This macro does not check for an unexpected end of the
- * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
- */
-#define SKIP_FIELDDESCRIPTOR(utf_ptr)                                                  \
-       do { while (*(utf_ptr)=='[') (utf_ptr)++;                                       \
-               if (*(utf_ptr)++=='L')                                                                  \
-                       while(*(utf_ptr)++ != ';') /* skip */; } while(0)
-
-/* SKIP_FIELDDESCRIPTOR_SAFE:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * Input:
- *     utf_ptr....points to first char of descriptor
- *     end_ptr....points to first char after the end of the string
- *     errorflag..must be initialized (to false) by the caller!
- * Output:
- *     utf_ptr....points to first char after the descriptor
- *     errorflag..set to true if the string ended unexpectedly
- */
-#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag)                   \
-       do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++;     \
-               if ((utf_ptr) == (end_ptr))                                                                             \
-                       (errorflag) = true;                                                                                     \
-               else                                                                                                                    \
-                       if (*(utf_ptr)++=='L') {                                                                        \
-                               while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';')    \
-                                       /* skip */;                                                                                     \
-                               if ((utf_ptr)[-1] != ';')                                                               \
-                                       (errorflag) = true; }} while(0)
-
-
 /* Synchronization ************************************************************/
 
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
index f31e75410232c10ee6b8dd60af344cad2dea6964..f7872316285d5eaabbcb57140c336470963c76cd 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: codegen.inc.h 2125 2005-03-29 22:20:49Z twisti $
+   $Id: codegen.inc.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -50,7 +50,7 @@ typedef struct threadcritnodetemp threadcritnodetemp;
 
 #include "types.h"
 #include "vm/global.h"
-#include "vm/class.h"
+#include "vm/references.h"
 #include "vm/method.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/reg.h"
index 421539d911f737f358272a05d10b7d5866b67ac4..a13c8362c5c386ad0ed687646db0319be2623d6b 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Carolyn Oates
 
-   $Id: parseXTA.h 2160 2005-03-30 20:08:29Z twisti $
+   $Id: parseXTA.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -39,6 +39,7 @@ typedef struct xtainfo xtainfo;
 typedef        struct xtafldinfo xtafldinfo;
 
 
+#include "toolbox/list.h"
 #include "vm/global.h"
 #include "vm/jit/inline/sets.h"
 
index b1c3cbfe6ce69fc6c4128e851663d3031dd5b6a6..7ece8d1119e5a8d6bd12bd5441b1d58ae632cfb2 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Carolyn Oates
 
-   $Id: sets.c 2107 2005-03-28 22:44:28Z twisti $
+   $Id: sets.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -39,6 +39,7 @@
 #include "vm/linker.h"
 #include "vm/loader.h"
 #include "vm/tables.h"
+#include "vm/class.h"
 #include "vm/jit/inline/sets.h"
 
 
index 2c3ed3afdf0bb966ef64c01299a15bfb31aa57d4..fe9acf08fb4b99875933032dd204d790b76faeee 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Carolyn Oates
 
-   $Id: sets.h 2107 2005-03-28 22:44:28Z twisti $
+   $Id: sets.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -42,9 +42,9 @@ typedef struct classSet     classSet;
 typedef struct classSetNode classSetNode;
 
 
-#include "types.h"
 #include "vm/global.h"
 #include "vm/method.h"
+#include "vm/field.h"
 
 
 /*------------ Method /Class Used Markers -------------------------------*/                 
index 38887504f3ba5d365e7028ee6788b24ceb1d9e66..e6f0bd7b51597744ce107c6169c4348eb59e2e7f 100644 (file)
@@ -29,7 +29,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: jit.h 2135 2005-03-30 09:55:26Z twisti $
+   $Id: jit.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -47,8 +47,8 @@ typedef struct subroutineinfo subroutineinfo;
 
 
 #include "toolbox/chain.h"
-#include "vm/class.h"
 #include "vm/global.h"
+#include "vm/references.h"
 #include "vm/method.h"
 #include "vm/jit/codegen.inc.h"
 #include "vm/jit/verify/typeinfo.h"
index d205b990c505edb978cb23d6ad2ee5184a375c3c..1e00f44782d4b73f9d9d0ffd3a6f21c758457da8 100644 (file)
@@ -29,7 +29,7 @@
    Changes: Edwin Steiner
             Christian Thalinger
 
-   $Id: stack.c 2163 2005-03-30 20:18:18Z twisti $
+   $Id: stack.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -2140,7 +2140,7 @@ void icmd_print_stack(codegendata *cd, stackptr s)
                                else if (IS_FLT_DBL_TYPE(s->type))
                                        printf(" F%02d", s->regoff);
                                else {
-                                       printf(" %3s", regs[s->regoff]);
+                                       printf(" R%02d", s->regoff);
                                }
                                break;
                        case STACKVAR:
@@ -2163,7 +2163,7 @@ void icmd_print_stack(codegendata *cd, stackptr s)
                                else if (IS_FLT_DBL_TYPE(s->type))
                                        printf(" f%02d", s->regoff);
                                else {
-                                       printf(" %3s", regs[s->regoff]);
+                                       printf(" r%02d", s->regoff);
                                }
                                break;
                        case STACKVAR:
@@ -2286,7 +2286,7 @@ void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd)
                                else if ((j == TYPE_FLT) || (j == TYPE_DBL))
                                        printf("f%02d", rd->locals[i][j].regoff);
                                else {
-                                       printf("%3s", regs[rd->locals[i][j].regoff]);
+                                       printf("r%02d", rd->locals[i][j].regoff);
                                }
                        }
                printf("\n");
@@ -2312,7 +2312,7 @@ void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd)
                                                else if ((j == TYPE_FLT) || (j == TYPE_DBL))
                                                        printf("F%02d", rd->interfaces[i][j].regoff);
                                                else {
-                                                       printf("%3s", regs[rd->interfaces[i][j].regoff]);
+                                                       printf("R%02d", rd->interfaces[i][j].regoff);
                                                }
                                        }
                                        else {
@@ -2321,7 +2321,7 @@ void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd)
                                                else if ((j == TYPE_FLT) || (j == TYPE_DBL))
                                                        printf("f%02d", rd->interfaces[i][j].regoff);
                                                else {
-                                                       printf("%3s", regs[rd->interfaces[i][j].regoff]);
+                                                       printf("r%02d", rd->interfaces[i][j].regoff);
                                                }
                                        }
                                }
index fd68a008316cbbfa8f3ba2b1f3088475e10a3fa7..a382de3c2475313685fdadf284b7641893b1b180 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Christian Thalinger
 
-   $Id: stack.h 1735 2004-12-07 14:33:27Z twisti $
+   $Id: stack.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -34,8 +34,8 @@
 #ifndef _STACK_H
 #define _STACK_H
 
-#include "vm/exceptions.h"
 #include "vm/global.h"
+#include "vm/exceptions.h"
 #include "vm/jit/reg.h"
 
 
index 6e9cc9e802b22532771bf5680846af1d4c2e76d9..db8baa00f4885cc63ef5459556d8fa7f98167d02 100644 (file)
 
    Changes:
 
-   $Id: genoffsets.c 2122 2005-03-29 22:12:06Z twisti $
+   $Id: genoffsets.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 
 #include <stdio.h>
 
-#include "config.h"
-#include "types.h"
+#include "vm/global.h"
 #include "mm/memory.h"
 #include "vm/linker.h"
 #include "vm/method.h"
-#include "vm/global.h"
+#include "vm/class.h"
 #include "vm/jit/asmpart.h"
 
 
index 548b71ae0b77de516556c8cf985546d65a2fd8cc..b2dedc93966e3ec571bb12e260f2be3341c3e6c6 100644 (file)
 
    Authors: Edwin Steiner
 
-   $Id: typecheck.c 2081 2005-03-25 13:45:26Z edwin $
+   $Id: typecheck.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
+#include <assert.h>
 #include <string.h>
 
 #include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
@@ -37,7 +38,6 @@
 #ifdef CACAO_TYPECHECK
 
 #include "types.h"
-/*  #include "main.h" */
 #include "mm/memory.h"
 #include "toolbox/logging.h"
 #include "native/native.h"
 #include "vm/tables.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/stack.h"
+#include "vm/access.h"
+#include "vm/resolve.h"
 
 
 /****************************************************************************/
 /* DEBUG HELPERS                                                            */
 /****************************************************************************/
 
+#ifdef TYPECHECK_DEBUG
+#define TYPECHECK_ASSERT(cond)  assert(cond)
+#else
+#define TYPECHECK_ASSERT(cond)
+#endif
+
 #ifdef TYPECHECK_VERBOSE_OPT
 bool typecheckverbose = false;
 #define DOLOG(action)  do { if (typecheckverbose) {action;} } while(0)
@@ -80,6 +88,7 @@ bool typecheckverbose = false;
 #define LOGSTR2(str,a,b)   DOLOG(dolog_plain(str,a,b))
 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
 #define LOGSTRu(utf)       DOLOG(log_plain_utf(utf))
+#define LOGNAME(c)         DOLOG(do {log_plain_utf(IS_CLASSREF(c) ? c.ref->name : c.cls->name);} while(0))
 #else
 #define LOG(str)
 #define LOG1(str,a)
@@ -94,6 +103,7 @@ bool typecheckverbose = false;
 #define LOGSTR2(str,a,b)
 #define LOGSTR3(str,a,b,c)
 #define LOGSTRu(utf)
+#define LOGNAME(c)
 #endif
 
 #ifdef TYPECHECK_VERBOSE_IMPORTANT
@@ -116,7 +126,8 @@ typestack_print(FILE *file,stackptr stack)
 {
 #ifdef TYPEINFO_DEBUG
     while (stack) {
-        typeinfo_print_stacktype(file,stack->type,&stack->typeinfo);
+               /*fprintf(file,"<%p>",stack);*/
+        typeinfo_print_stacktype(file,stack->type,&(stack->typeinfo));
         stack = stack->prev;
         if (stack) fprintf(file," ");
     }
@@ -290,10 +301,7 @@ typestack_copy(stackptr dst,stackptr y,typevector *selected)
 static void
 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
 {
-#ifdef TYPECHECK_DEBUG
-       if (dst->type != TYPE_ADDRESS)
-               panic("Internal error: Storing returnAddress in non-address slot");
-#endif
+       TYPECHECK_ASSERT(dst->type == TYPE_ADDRESS);
        
        TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
        for (;loc; loc=loc->alt) {
@@ -367,14 +375,9 @@ typestack_separable_with(stackptr a,stackptr b,int kb)
        typeinfo_retaddr_set *setb;
        
        for (; a; a = a->prev, b = b->prev) {
-#ifdef TYPECHECK_DEBUG
-               if (!b) panic("Internal error: typestack_separable_from: different depth");
-#endif
+               TYPECHECK_ASSERT(b);
                if (TYPESTACK_IS_RETURNADDRESS(a)) {
-#ifdef TYPECHECK_DEBUG
-                       if (!TYPESTACK_IS_RETURNADDRESS(b))
-                               panic("Internal error: typestack_separable_from: unmergable stacks");
-#endif
+                       TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
                        seta = TYPESTACK_RETURNADDRESSSET(a);
                        setb = TYPESTACK_RETURNADDRESSSET(b);
                        RETURNADDRESSSET_SEEK(setb,kb);
@@ -383,9 +386,7 @@ typestack_separable_with(stackptr a,stackptr b,int kb)
                                if (seta->addr != setb->addr) return true;
                }
        }
-#ifdef TYPECHECK_DEBUG
-       if (b) panic("Internal error: typestack_separable_from: different depth");
-#endif
+       TYPECHECK_ASSERT(!b);
        return false;
 }
 
@@ -397,14 +398,9 @@ typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
        typeinfo_retaddr_set *setb;
 
        for (; a; a = a->prev, b = b->prev) {
-#ifdef TYPECHECK_DEBUG
-               if (!b) panic("Internal error: typestack_separable_from: different depth");
-#endif
+               TYPECHECK_ASSERT(b);
                if (TYPESTACK_IS_RETURNADDRESS(a)) {
-#ifdef TYPECHECK_DEBUG
-                       if (!TYPESTACK_IS_RETURNADDRESS(b))
-                               panic("Internal error: typestack_separable_from: unmergable stacks");
-#endif
+                       TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
                        seta = TYPESTACK_RETURNADDRESSSET(a);
                        setb = TYPESTACK_RETURNADDRESSSET(b);
                        RETURNADDRESSSET_SEEK(seta,ka);
@@ -413,9 +409,7 @@ typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
                        if (seta->addr != setb->addr) return true;
                }
        }
-#ifdef TYPECHECK_DEBUG
-       if (b) panic("Internal error: typestack_separable_from: different depth");
-#endif
+       TYPECHECK_ASSERT(!b);
        return false;
 }
 
@@ -622,11 +616,11 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, c
                          /* In the cases below, definingclass cannot be an interface */
                          
                  case 0:
-                         if (definingclass->packagename != methodclass->packagename)
+                         if (!SAME_PACKAGE(definingclass,methodclass))
                                  return false;
                          break;
                  case ACC_PROTECTED:
-                         if (definingclass->packagename != methodclass->packagename) {
+                         if (!SAME_PACKAGE(definingclass,methodclass)) {
                                  if (!builtin_isanysubclass(methodclass,implementingclass))
                                          return false;
                                  
@@ -660,8 +654,8 @@ is_accessible(int flags,classinfo *definingclass,classinfo *implementingclass, c
                        && !TYPEINFO_IS_NULLTYPE(*instance)
                        && !TYPEINFO_IS_NEWOBJECT(*instance))
                {
-                       if (!typeinfo_is_assignable_to_classinfo(instance,
-                                                                                                        implementingclass))
+                       if (!typeinfo_is_assignable_to_class(instance,
+                                                                                                CLASSREF_OR_CLASSINFO(implementingclass)))
                        {
                                LOG("instance not assignable");
                                LOGINFO(instance);
@@ -845,7 +839,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
        typedescriptor returntype;        /* return type of current method */
     u1 *ptype;                     /* parameter types of called method */
     typeinfo *pinfo;           /* parameter typeinfos of called method */
-    int rtype;                         /* return type of called method */
+    u1 rtype;                          /* return type of called method */
     typeinfo rinfo;       /* typeinfo for return type of called method */
        
     stackptr dst;               /* output stack of current instruction */
@@ -868,7 +862,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
 #endif
 
     LOGSTR("\n==============================================================================\n");
-    /*DOLOG( show_icmd_method(cd->method,cd,rd));*/
+    DOLOG( show_icmd_method(cd->method,cd,rd));
     LOGSTR("\n==============================================================================\n");
     LOGimpSTR("Entering typecheck: ");
     LOGimpSTRu(cd->method->name);
@@ -900,7 +894,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
         {
             /*show_icmd_method(cd->method,cd,rd);*/
             LOGSTR1("block flags: %d\n",bptr->flags); LOGFLUSH;
-            panic("Internal error: Unexpected block flags in typecheck()");
+                       TYPECHECK_ASSERT(false);
         }
 #endif
         if (bptr->flags >= BBFINISHED) {
@@ -956,7 +950,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
     LOG("'this' argument set.\n");
 
     /* the rest of the arguments and the return type */
-    i = typedescriptors_init_from_method_args(td, m->descriptor,
+    i = typedescriptors_init_from_methoddesc(td, m->parseddesc,
                                                                                          i,
                                                                                          true, /* two word types use two slots */
                                                                                          &returntype);
@@ -1038,6 +1032,10 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                 iptr = bptr->iinstr;
                 while (--len >= 0)  {
                                        TYPECHECK_COUNT(stat_ins);
+                                       
+                                       DOLOG(typestate_print(get_logfile(),curstack,localset,numlocals));
+                                       LOGNL; LOGFLUSH;
+
                     DOLOG(show_icmd(iptr,false)); LOGNL; LOGFLUSH;
                         
                     opcode = iptr->opc;
@@ -1233,7 +1231,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                          if (type != fi->type)
                                                                  panic("PUTFIELD(CONST) type mismatch");
                                                          if (type == TYPE_ADR) {
-                                                                 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
+                                                                 typeinfo_init_from_typedesc(fi->parseddesc,NULL,&rinfo);
                                                                  if (!typeinfo_is_assignable(temptip,
                                                                                                                          &rinfo))
                                                                          panic("PUTFIELD(CONST) reference type not assignable");
@@ -1278,7 +1276,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                          if (type != fi->type)
                                                                  panic("PUTSTATIC(CONST) type mismatch");
                                                          if (type == TYPE_ADR) {
-                                                                 TYPEINFO_INIT_FROM_FIELDINFO(rinfo,fi);
+                                                                 typeinfo_init_from_typedesc(fi->parseddesc,NULL,&rinfo);
                                                                  if (!typeinfo_is_assignable(temptip,
                                                                                                                          &rinfo))
                                                                          panic("PUTSTATIC(CONST) reference type not assignable");
@@ -1296,13 +1294,13 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                           
                           {
                               fieldinfo *fi = (fieldinfo *)(iptr->val.a);
-
+                                                         
                                                          if (!is_accessible(fi->flags,fi->class,fi->class,myclass,
                                                                                                 &(curstack->typeinfo)))
                                                                  panic("GETFIELD: field is not accessible");
                                                          
                               if (dst->type == TYPE_ADR) {
-                                  TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
+                                  typeinfo_init_from_typedesc(fi->parseddesc,NULL,&(dst->typeinfo));
                               }
                           }
                           maythrow = true;
@@ -1325,7 +1323,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                        }
 
                               if (dst->type == TYPE_ADR) {
-                                  TYPEINFO_INIT_FROM_FIELDINFO(dst->typeinfo,fi);
+                                  typeinfo_init_from_typedesc(fi->parseddesc,NULL,&(dst->typeinfo));
                               }
                           }
                           maythrow = true;
@@ -1336,7 +1334,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
 
                       case ICMD_ARRAYLENGTH:
                           if (!TYPEINFO_MAYBE_ARRAY(curstack->typeinfo)
-                                                         && curstack->typeinfo.typeclass != pseudo_class_Arraystub)
+                                                         && curstack->typeinfo.typeclass.cls != pseudo_class_Arraystub)
                               panic("illegal instruction: ARRAYLENGTH on non-array");
                           maythrow = true;
                           break;
@@ -1555,8 +1553,8 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                           /* RETURNS AND THROW                    */
 
                       case ICMD_ATHROW:
-                          if (!typeinfo_is_assignable_to_classinfo(
-                                   &curstack->typeinfo,class_java_lang_Throwable))
+                          if (!typeinfo_is_assignable_to_class(
+                                   &curstack->typeinfo,CLASSREF_OR_CLASSINFO(class_java_lang_Throwable)))
                               panic("illegal instruction: ATHROW on non-Throwable");
                           superblockend = true;
                           maythrow = true;
@@ -1642,7 +1640,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                          bool specialmethod = (mi->name->text[0] == '<');
                               bool callinginit = (opcode == ICMD_INVOKESPECIAL && mi->name == name_init);
                               instruction *ins;
-                              classinfo *initclass;
+                              classref_or_classinfo initclass;
 
                                                          if (specialmethod && !callinginit)
                                                                  panic("Invalid invocation of special method");
@@ -1664,9 +1662,9 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                   TYPEINFO_INIT_CLASSINFO(pinfo[0],mi->class);
                                   i++;
                               }
-                              typeinfo_init_from_method_args(mi->descriptor,ptype+i,pinfo+i,
-                                                             MAXPARAMS-i,false,
-                                                             &rtype,&rinfo);
+                              typeinfo_init_from_methoddesc(mi->parseddesc,ptype+i,pinfo+i,
+                                                            MAXPARAMS-i,false,
+                                                            &rtype,&rinfo);
 
                               /* check parameter types */
                               srcstack = curstack;
@@ -1687,14 +1685,11 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                           /* get the address of the NEW instruction */
                                           LOGINFO(&(srcstack->typeinfo));
                                           ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(srcstack->typeinfo);
-                                          initclass = (ins) ? (classinfo*)ins[-1].val.a : m->class;
-                                          LOGSTR("class: "); LOGSTRu(initclass->name); LOGNL;
-
-                                                                                 /* check type */
-                                                                                 /* (This is checked below.) */
-/*                                                                               TYPEINFO_INIT_CLASSINFO(tempinfo,initclass); */
-/*                                           if (!typeinfo_is_assignable(&tempinfo,pinfo+0)) */
-/*                                               panic("Parameter reference type mismatch in <init> invocation"); */
+                                                                                 if (ins)
+                                                                                         initclass = CLASSREF_OR_CLASSINFO(ins[-1].val.a);
+                                                                                 else
+                                              initclass.cls = m->class;
+                                          LOGSTR("class: "); LOGNAME(initclass); LOGNL;
                                       }
                                       else {
                                           if (!typeinfo_is_assignable(&(srcstack->typeinfo),pinfo+i))
@@ -1753,7 +1748,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                                          TYPESTACK_COPY(sp,copy);
                                                                                  }
                                                                                  
-                                          TYPEINFO_INIT_CLASSINFO(srcstack->typeinfo,initclass);
+                                          TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(srcstack->typeinfo,initclass);
                                       }
                                       srcstack = srcstack->prev;
                                   }
@@ -1762,10 +1757,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
 
                                   /* initializing the 'this' reference? */
                                   if (!ins) {
-#ifdef TYPECHECK_DEBUG
-                                                                         if (!initmethod)
-                                                                                 panic("Internal error: calling <init> on this in non-<init> method.");
-#endif
+                                                                         TYPECHECK_ASSERT(initmethod);
                                                                          /* must be <init> of current class or direct superclass */
                                                                          if (mi->class != m->class && mi->class != m->class->super)
                                                                                  panic("<init> calling <init> of the wrong class");
@@ -1777,7 +1769,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                  else {
                                                                          /* initializing an instance created with NEW */
                                                                          /* XXX is this strictness ok? */
-                                                                         if (mi->class != initclass)
+                                                                         if (mi->class != initclass.cls) /* XXX change to classref */
                                                                                  panic("Calling <init> method of the wrong class");
                                                                  }
                               }
@@ -1834,7 +1826,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                         != iptr->val.fp) builtindesc++;
                                                          if (!builtindesc->opcode) {
                                                                  dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
-                                                                 panic("Internal error: builtin not found in table");
+                                                                 TYPECHECK_ASSERT(false);
                                                          }
                                                          TYPECHECK_ARGS3(builtindesc->type_s3,builtindesc->type_s2,builtindesc->type_s1);
                                                  }
@@ -1887,7 +1879,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                         != iptr->val.fp) builtindesc++;
                                                          if (!builtindesc->opcode) {
                                                                  dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
-                                                                 panic("Internal error: builtin not found in table");
+                                                                 TYPECHECK_ASSERT(false);
                                                          }
                                                          TYPECHECK_ARGS2(builtindesc->type_s2,builtindesc->type_s1);
                                                  }
@@ -1901,8 +1893,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                               if (iptr[-1].opc != ICMD_ACONST)
                                   panic("illegal instruction: builtin_new without classinfo");
                                                          cls = (classinfo *) iptr[-1].val.a;
-                                                         if (!cls->linked)
-                                                                 panic("Internal error: NEW with unlinked class");
+                                                         TYPECHECK_ASSERT(cls->linked);
                                                          /* The following check also forbids array classes and interfaces: */
                                                          if ((cls->flags & ACC_ABSTRACT) != 0)
                                                                  panic("Invalid instruction: NEW creating instance of abstract class");
@@ -1947,7 +1938,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                                                                         != iptr->val.fp) builtindesc++;
                                                          if (!builtindesc->opcode) {
                                                                  dolog("Builtin not in table: %s",icmd_builtin_name(iptr->val.fp));
-                                                                 panic("Internal error: builtin not found in table");
+                                                                 TYPECHECK_ASSERT(false);
                                                          }
                                                          TYPECHECK_ARGS1(builtindesc->type_s1);
                                                  }
@@ -1982,14 +1973,14 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                       case ICMD_AASTORE:
                           LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-bptr->iinstr));
                                                  LOG("Should have been converted to builtin function call.");
-                          panic("Internal error: unexpected instruction encountered");
+                                                 TYPECHECK_ASSERT(false);
                           break;
                                                      
                       case ICMD_READONLY_ARG:
                       case ICMD_CLEAR_ARGREN:
                           LOG2("ICMD %d at %d\n", iptr->opc, (int)(iptr-bptr->iinstr));
                                                  LOG("Should have been replaced in stack.c.");
-                          panic("Internal error: unexpected pseudo instruction encountered");
+                                                 TYPECHECK_ASSERT(false);
                           break;
 #endif
                                                  
@@ -2142,8 +2133,8 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                         i = 0;
                         while (handlers[i]) {
                                                        TYPECHECK_COUNT(stat_handlers_reached);
-                                                       cls = handlers[i]->catchtype;
-                                                       excstack.typeinfo.typeclass = (cls) ? cls
+                                                       cls = handlers[i]->catchtype; /* XXX change to classref */
+                                                       excstack.typeinfo.typeclass.cls = (cls) ? cls
                                                                : class_java_lang_Throwable;
                                                        repeat |= typestate_reach(cd,rd, localbuf,bptr,
                                                                                                          handlers[i]->handler,
@@ -2154,6 +2145,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                         }
                     }
 
+                                       LOG("next instruction");
                     iptr++;
                 } /* while instructions */
 
@@ -2198,7 +2190,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
     } while (repeat);
 
 #ifdef TYPECHECK_STATISTICS
-       dolog("Typechecker did %4d iterations",count_iterations);
+       LOG1("Typechecker did %4d iterations",count_iterations);
        TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
        TYPECHECK_COUNTIF(jsrencountered,stat_typechecked_jsr);
 #endif
@@ -2214,7 +2206,7 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
                {
                        LOG2("block L%03d has invalid flags after typecheck: %d",
                                 m->basicblocks[i].debug_nr,m->basicblocks[i].flags);
-                       panic("Invalid block flags after typecheck");
+                       TYPECHECK_ASSERT(false);
                }
        }
 #endif
@@ -2247,4 +2239,5 @@ methodinfo *typecheck(methodinfo *m, codegendata *cd, registerdata *rd)
  * c-basic-offset: 4
  * tab-width: 4
  * End:
+ * vim:noexpandtab:sw=4:ts=4:
  */
index 0f6e8fde0b9272ebf3615f2b13ceff8003f0cd7f..4b943bf9d73dbc499b5e5881aae0582178159e39 100644 (file)
 
    Authors: Edwin Steiner
 
-   $Id: typeinfo.c 2161 2005-03-30 20:08:53Z twisti $
+   $Id: typeinfo.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
-
+#include <assert.h>
 #include <string.h>
 
 #include "mm/memory.h"
 #include "vm/tables.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/verify/typeinfo.h"
+#include "vm/descriptor.h"
+#include "vm/resolve.h"
+
 
-#define CLASS_IS_ARRAY(cls)                                     \
-       ((cls)->vftbl->arraydesc != NULL)
+/* check if a linked class is an array class. Only use for linked classes! */
+#define CLASSINFO_IS_ARRAY(clsinfo)  ((clsinfo)->vftbl->arraydesc != NULL)
 
-#define CLASS_IMPLEMENTS_INTERFACE(cls,index)                   \
+#define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index)                   \
     ( ((index) < (cls)->vftbl->interfacetablelength)            \
       && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
 
+/******************************************************************************/
+/* DEBUG HELPERS                                                              */
+/******************************************************************************/
+
+#ifdef TYPEINFO_DEBUG
+#define TYPEINFO_ASSERT(cond)  assert(cond)
+#else
+#define TYPEINFO_ASSERT(cond)
+#endif
+
 /**********************************************************************/
 /* TYPEVECTOR FUNCTIONS                                               */
 /**********************************************************************/
@@ -183,7 +196,8 @@ typevectorset_store_twoword(typevector *vec,int index,int type)
 }
 
 void
-typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,
+typevectorset_init_object(typevector *set,void *ins,
+                                                 classref_or_classinfo initclass,
                                                  int size)
 {
        int i;
@@ -194,7 +208,7 @@ typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,
                                && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
                                && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
                        {
-                               TYPEINFO_INIT_CLASSINFO(set->td[i].info,initclass);
+                               TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(set->td[i].info,initclass);
                        }
                }
        }
@@ -334,27 +348,34 @@ typevectorset_collapse(typevector *dst,int size)
 bool
 typeinfo_is_array(typeinfo *info)
 {
+       TYPEINFO_ASSERT(info);
     return TYPEINFO_IS_ARRAY(*info);
 }
 
 bool
 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
 {
+       TYPEINFO_ASSERT(info);
     return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
 }
 
 bool
 typeinfo_is_array_of_refs(typeinfo *info)
 {
+       TYPEINFO_ASSERT(info);
     return TYPEINFO_IS_ARRAY_OF_REFS(*info);
 }
 
-static
-bool
+static bool
 interface_extends_interface(classinfo *cls,classinfo *interf)
 {
     int i;
     
+       TYPEINFO_ASSERT(cls);
+       TYPEINFO_ASSERT(interf);
+       TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
+       TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
+
     /* first check direct superinterfaces */
     for (i=0; i<cls->interfacescount; ++i) {
         if (cls->interfaces[i] == interf)
@@ -370,16 +391,19 @@ interface_extends_interface(classinfo *cls,classinfo *interf)
     return false;
 }
 
-static
-bool
+static bool
 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))
+               if (!load_class_bootstrap(cls)) /* XXX */
                        return false;
 
        if (!cls->linked)
-               if (!link_class(cls))
+               if (!link_class(cls)) /* XXX */
                        return false;
 
     if (cls->flags & ACC_INTERFACE) {
@@ -391,15 +415,19 @@ classinfo_implements_interface(classinfo *cls,classinfo *interf)
         return interface_extends_interface(cls,interf);
     }
 
-    return CLASS_IMPLEMENTS_INTERFACE(cls,interf->index);
+    return CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
 }
 
-bool mergedlist_implements_interface(typeinfo_mergedlist *merged,
-                                     classinfo *interf)
+tristate_t 
+mergedlist_implements_interface(typeinfo_mergedlist *merged,
+                                classinfo *interf)
 {
     int i;
-    classinfo **mlist;
+    classref_or_classinfo *mlist;
     
+       TYPEINFO_ASSERT(interf);
+       TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
+
     /* Check if there is an non-empty mergedlist. */
     if (!merged)
         return false;
@@ -410,13 +438,16 @@ bool mergedlist_implements_interface(typeinfo_mergedlist *merged,
     mlist = merged->list;
     i = merged->count;
     while (i--) {
-        if (!classinfo_implements_interface(*mlist++,interf))
+               if (IS_CLASSREF(*mlist)) {
+                       return MAYBE;
+               }
+        if (!classinfo_implements_interface((mlist++)->cls,interf))
             return false;
     }
     return true;
 }
 
-bool
+tristate_t
 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
                             classinfo *interf)
 {
@@ -436,45 +467,35 @@ merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
     return (merged && mergedlist_implements_interface(merged,interf));
 }
 
-bool
+tristate_t
 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
 {
-    /* DEBUG CHECK: dest must not have a merged list. */
-#ifdef TYPEINFO_DEBUG
-    if (dest->merged)
-        panic("Internal error: typeinfo_is_assignable on merged destination.");
-#endif
+       TYPEINFO_ASSERT(value);
+       TYPEINFO_ASSERT(dest);
+       TYPEINFO_ASSERT(dest->merged == NULL);
 
-       return typeinfo_is_assignable_to_classinfo(value,dest->typeclass);
+       return typeinfo_is_assignable_to_class(value,dest->typeclass);
 }
 
-bool
-typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
+tristate_t
+typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
 {
+       classref_or_classinfo c;
     classinfo *cls;
+       utf *classname;
+
+       TYPEINFO_ASSERT(value);
 
-    cls = value->typeclass;
+    c = value->typeclass;
 
     /* assignments of primitive values are not checked here. */
-    if (!cls && !dest)
+    if (!c.any && !dest.any)
         return true;
 
     /* primitive and reference types are not assignment compatible. */
-    if (!cls || !dest)
+    if (!c.any || !dest.any)
         return false;
 
-       /* maybe we need to load and link the class */
-       if (!cls->loaded)
-               load_class_bootstrap(cls);
-
-       if (!cls->linked)
-               link_class(cls);
-
-#ifdef TYPEINFO_DEBUG
-    if (!dest->linked)
-        panic("Internal error: typeinfo_is_assignable_to_classinfo: unlinked class.");
-#endif
-       
     /* the null type can be assigned to any type */
     if (TYPEINFO_IS_NULLTYPE(*value))
         return true;
@@ -483,13 +504,70 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
     if (TYPEINFO_IS_NEWOBJECT(*value))
         return false;
 
-    if (dest->flags & ACC_INTERFACE) {
+       if (IS_CLASSREF(c)) {
+               /* The value type is an unresolved class reference. */
+               classname = c.ref->name;
+       }
+       else {
+               classname = c.cls->name;
+       }
+
+       if (IS_CLASSREF(dest)) {
+               /* the destination type is an unresolved class reference */
+               /* In this case we cannot tell a lot about assignability. */
+
+               /* the common case of value and dest type having the same classname */
+               if (dest.ref->name == classname && !value->merged)
+                       return true;
+
+               /* we cannot tell if value is assignable to dest, so we */
+               /* leave it up to the resolving code to check this      */
+               return MAYBE;
+       }
+
+       /* { we know that dest is a loaded class } */
+
+       if (IS_CLASSREF(c)) {
+               /* the value type is an unresolved class reference */
+               
+               /* the common case of value and dest type having the same classname */
+               if (dest.cls->name == classname)
+                       return true;
+
+               /* we cannot tell if value is assignable to dest, so we */
+               /* leave it up to the resolving code to check this      */
+               return MAYBE;
+       }
+
+       /* { we know that both c and dest are loaded classes } */
+
+       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);
+
+       /* maybe we need to link the classes */
+       if (!cls->linked)
+               link_class(cls); /* XXX */
+       if (!dest.cls->linked)
+               link_class(dest.cls); /* XXX */
+
+       /* { we know that both c and dest are linked classes } */
+       TYPEINFO_ASSERT(cls->linked);
+       TYPEINFO_ASSERT(dest.cls->linked);
+
+    if (dest.cls->flags & ACC_INTERFACE) {
         /* We are assigning to an interface type. */
-        return merged_implements_interface(cls,value->merged,dest);
+        return merged_implements_interface(cls,value->merged,dest.cls);
     }
 
-    if (CLASS_IS_ARRAY(dest)) {
-               arraydescriptor *arraydesc = dest->vftbl->arraydesc;
+    if (CLASSINFO_IS_ARRAY(dest.cls)) {
+               arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
                int dimension = arraydesc->dimension;
                classinfo *elementclass = (arraydesc->elementvftbl)
                        ? arraydesc->elementvftbl->class : NULL;
@@ -498,16 +576,16 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
         if (!TYPEINFO_IS_ARRAY(*value))
             return false;
 
-        /* {Both value and dest are array types.} */
+        /* {Both value and dest.cls are array types.} */
 
-        /* value must have at least the dimension of dest. */
+        /* value must have at least the dimension of dest.cls. */
         if (value->dimension < dimension)
             return 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 */
+             * element type of dest.cls */
 
                        if (!elementclass) return false;
             
@@ -521,12 +599,12 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
             return class_issubclass(pseudo_class_Arraystub,elementclass);
         }
 
-        /* {value and dest have the same dimension} */
+        /* {value and dest.cls have the same dimension} */
 
         if (value->elementtype != arraydesc->elementtype)
             return false;
 
-        if (value->elementclass) {
+        if (value->elementclass.any) {
             /* We are assigning an array of objects so we have to
              * check if the elements are assignable.
              */
@@ -534,25 +612,37 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
             if (elementclass->flags & ACC_INTERFACE) {
                 /* We are assigning to an interface type. */
 
-                return merged_implements_interface(value->elementclass,
+                return merged_implements_interface(value->elementclass.cls,
                                                    value->merged,
                                                    elementclass);
             }
             
             /* We are assigning to a class type. */
-            return class_issubclass(value->elementclass,elementclass);
+            return class_issubclass(value->elementclass.cls,elementclass);
         }
 
         return true;
     }
 
-    /* {dest is not an array} */
+    /* {dest.cls is not an array} */
+    /* {dest.cls is a loaded class} */
+
+       /* If there are any unresolved references in the merged list, we cannot */
+       /* tell if the assignment will be ok.                                   */
+       /* This can only happen when cls is java.lang.Object                    */
+       if (cls == class_java_lang_Object && value->merged) {
+               classref_or_classinfo *mlist = value->merged->list;
+               int i = value->merged->count;
+               while (i--)
+                       if (IS_CLASSREF(*mlist++))
+                               return MAYBE;
+       }
         
     /* We are assigning to a class type */
     if (cls->flags & ACC_INTERFACE)
         cls = class_java_lang_Object;
     
-    return class_issubclass(cls,dest);
+    return class_issubclass(cls,dest.cls);
 }
 
 /**********************************************************************/
@@ -560,229 +650,214 @@ typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
 /* The following functions fill in uninitialized typeinfo structures. */
 /**********************************************************************/
 
-void
-typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr)
+bool
+typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
 {
-    classinfo *cls;
-    char *end;
-
-    cls = class_from_descriptor(utf_ptr,end_ptr,&end,
-                                                               CLASSLOAD_NULLPRIMITIVE
-                                                               | CLASSLOAD_NEW
-                                                               | CLASSLOAD_NOVOID
-                                                               | CLASSLOAD_CHECKEND);
-
+       char *utf_ptr;
+       int len;
+       classinfo *cls;
+               
+       TYPEINFO_ASSERT(c.any);
+       TYPEINFO_ASSERT(info);
+
+       /* if necessary, try to resolve lazily */
+       if (!resolve_classref_or_classinfo(NULL /* XXX should now method */,
+                               c,resolveLazy,true,&cls))
+       {
+               panic("XXX could not resolve class reference"); /* XXX */
+               return false;
+       }
+       
        if (cls) {
-               if (!cls->loaded)
-                       load_class_bootstrap(cls);
-
-               if (!cls->linked)
-                       link_class(cls);
-
-               /* a class, interface or array descriptor */
                TYPEINFO_INIT_CLASSINFO(*info,cls);
-       } else {
-               /* a primitive type */
-               TYPEINFO_INIT_PRIMITIVE(*info);
+               return true;
+       }
+
+       /* {the type could no be resolved lazily} */
+
+       info->typeclass.ref = c.ref;
+       info->elementclass.any = NULL;
+       info->dimension = 0;
+       info->merged = NULL;
+
+       /* handle array type references */
+       utf_ptr = c.ref->name->text;
+       len = c.ref->name->blength;
+       if (*utf_ptr == '[') {
+               /* count dimensions */
+               while (*utf_ptr == '[') {
+                       utf_ptr++;
+                       info->dimension++;
+                       len--;
+               }
+               if (*utf_ptr == 'L') {
+                       utf_ptr++;
+                       len -= 2;
+                       info->elementtype = ARRAYTYPE_OBJECT;
+                       info->elementclass.ref = class_get_classref(c.ref->referer,utf_new(utf_ptr,len));
+               }
+               else {
+                       /* an array with primitive element type */
+                       /* should have been resolved above */
+                       TYPEINFO_ASSERT(false);
+               }
        }
+       return true;
 }
 
-int
-typeinfo_count_method_args(utf *d,bool twoword)
+void
+typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
 {
-    int args = 0;
-    char *utf_ptr = d->text;
-    char *end_pos = utf_end(d);
-    char c;
+       TYPEINFO_ASSERT(desc);
 
-    /* method descriptor must start with parenthesis */
-    if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
+#ifdef TYPEINFO_VERBOSE
+       fprintf(stderr,"typeinfo_init_from_typedesc(");
+       descriptor_debug_print_typedesc(stderr,desc);
+       fprintf(stderr,")\n");
+#endif
 
-       
-    /* check arguments */
-    while ((c = *utf_ptr) != ')') {
-               class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
-                                                         CLASSLOAD_SKIP | CLASSLOAD_NOVOID
-                                                         | CLASSLOAD_NULLPRIMITIVE);
-               args++;
-               if (twoword && (c == 'J' || c == 'D'))
-                       /* primitive two-word type */
-                       args++;
-    }
+       if (type)
+               *type = desc->type;
 
-    return args;
+       if (info) {
+               if (desc->type == TYPE_ADR) {
+                       TYPEINFO_ASSERT(desc->classref);
+                       TYPEINFO_INIT_CLASSREF(*info,desc->classref);
+               }
+               else {
+                       TYPEINFO_INIT_PRIMITIVE(*info);
+               }
+       }
 }
 
 void
-typeinfo_init_from_method_args(utf *desc,u1 *typebuf,typeinfo *infobuf,
-                               int buflen,bool twoword,
-                               int *returntype,typeinfo *returntypeinfo)
+typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
+                              int buflen,bool twoword,
+                              u1 *returntype,typeinfo *returntypeinfo)
 {
-    char *utf_ptr = desc->text;     /* current position in utf text   */
-    char *end_pos = utf_end(desc);  /* points behind utf string       */
+       int i;
     int args = 0;
-    classinfo *cls;
 
-    /* method descriptor must start with parenthesis */
-    if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
+       TYPEINFO_ASSERT(desc);
+       TYPEINFO_ASSERT(typebuf);
+       TYPEINFO_ASSERT(infobuf);
+
+#ifdef TYPEINFO_VERBOSE
+       fprintf(stderr,"typeinfo_init_from_methoddesc(");
+       descriptor_debug_print_methoddesc(stderr,desc);
+       fprintf(stderr,")\n");
+#endif
 
     /* check arguments */
-    while (utf_ptr != end_pos && *utf_ptr != ')') {
+    for (i=0; i<desc->paramcount; ++i) {
                if (++args > buflen)
-                       panic("Buffer too small for method arguments.");
-               
-        *typebuf++ = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
-                                                                                 CLASSLOAD_NEW
-                                                                                 | CLASSLOAD_NULLPRIMITIVE
-                                                                                 | CLASSLOAD_NOVOID);
-               
-               if (cls) {
-                       if (!cls->loaded)
-                               load_class_bootstrap(cls);
-
-                       if (!cls->linked)
-                               link_class(cls);
-
-                       TYPEINFO_INIT_CLASSINFO(*infobuf, cls);
-
-               } else {
-                       TYPEINFO_INIT_PRIMITIVE(*infobuf);
-               }
-               infobuf++;
+                       panic("Buffer too small for method arguments."); /* XXX */
 
+               typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++);
+               
                if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) {
                        if (++args > buflen)
-                               panic("Buffer too small for method arguments.");
+                               panic("Buffer too small for method arguments."); /* XXX */
                        *typebuf++ = TYPE_VOID;
                        TYPEINFO_INIT_PRIMITIVE(*infobuf);
                        infobuf++;
                }
     }
-    utf_ptr++; /* skip ')' */
 
     /* check returntype */
     if (returntype) {
-               *returntype = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
-                                                                                  CLASSLOAD_NULLPRIMITIVE
-                                                                                  | CLASSLOAD_NEW
-                                                                                  | CLASSLOAD_CHECKEND);
-
-               if (returntypeinfo) {
-                       if (cls) {
-                               if (!cls->loaded)
-                                       load_class_bootstrap(cls);
-
-                               if (!cls->linked)
-                                       link_class(cls);
-
-                               TYPEINFO_INIT_CLASSINFO(*returntypeinfo, cls);
+               typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo);
+       }
+}
 
-                       } else {
-                               TYPEINFO_INIT_PRIMITIVE(*returntypeinfo);
-                       }
-               }
+void
+typedescriptor_init_from_typedesc(typedescriptor *td,
+                                                                 typedesc *desc)
+{
+       td->type = desc->type;
+       if (td->type == TYPE_ADR) {
+               TYPEINFO_INIT_CLASSREF(td->info,desc->classref);
+       }
+       else {
+               TYPEINFO_INIT_PRIMITIVE(td->info);
        }
 }
 
 int
-typedescriptors_init_from_method_args(typedescriptor *td,
-                                                                         utf *desc,
-                                                                         int buflen,bool twoword,
-                                                                         typedescriptor *returntype)
+typedescriptors_init_from_methoddesc(typedescriptor *td,
+                                                                        methoddesc *desc,
+                                                                        int buflen,bool twoword,
+                                                                        typedescriptor *returntype)
 {
-    char *utf_ptr = desc->text;     /* current position in utf text   */
-    char *end_pos = utf_end(desc);  /* points behind utf string       */
+       int i;
     int args = 0;
-    classinfo *cls;
-
-    /* method descriptor must start with parenthesis */
-    if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
 
     /* check arguments */
-    while (utf_ptr != end_pos && *utf_ptr != ')') {
+    for (i=0; i<desc->paramcount; ++i) {
                if (++args > buflen)
-                       panic("Buffer too small for method arguments.");
-               
-        td->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
-                                                                               CLASSLOAD_NEW
-                                                                               | CLASSLOAD_NULLPRIMITIVE
-                                                                               | CLASSLOAD_NOVOID);
-               
-               if (cls) {
-                       if (!cls->loaded)
-                               load_class_bootstrap(cls);
-
-                       if (!cls->linked)
-                               link_class(cls);
+                       panic("Buffer too small for method arguments."); /* XXX */
 
-                       TYPEINFO_INIT_CLASSINFO(td->info, cls);
-                       
-               } else {
-                       TYPEINFO_INIT_PRIMITIVE(td->info);
-               }
+               typedescriptor_init_from_typedesc(td,desc->paramtypes + i);
                td++;
 
                if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
                        if (++args > buflen)
-                               panic("Buffer too small for method arguments.");
+                               panic("Buffer too small for method arguments."); /* XXX */
                        td->type = TYPE_VOID;
                        TYPEINFO_INIT_PRIMITIVE(td->info);
                        td++;
                }
     }
-    utf_ptr++; /* skip ')' */
 
     /* check returntype */
     if (returntype) {
-               returntype->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
-                                                                                               CLASSLOAD_NULLPRIMITIVE
-                                                                                               | CLASSLOAD_NEW
-                                                                                               | CLASSLOAD_CHECKEND);
-               if (cls) {
-                       if (!cls->loaded)
-                               load_class_bootstrap(cls);
-
-                       if (!cls->linked)
-                               link_class(cls);
-
-                       TYPEINFO_INIT_CLASSINFO(returntype->info,cls);
-
-               } else {
-                       TYPEINFO_INIT_PRIMITIVE(returntype->info);
-               }
+               typedescriptor_init_from_typedesc(returntype,&(desc->returntype));
        }
+
        return args;
 }
 
 void
 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
 {
-    vftbl_t *comp = NULL;
-
     if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
         TYPEINFO_INIT_NULLTYPE(*dst);
         return;
     }
     
     if (!TYPEINFO_IS_ARRAY(*srcarray))
-        panic("Trying to access component of non-array");
+        panic("Trying to access component of non-array"); /* XXX throw exception */
 
-    comp = srcarray->typeclass->vftbl->arraydesc->componentvftbl;
-    if (comp) {
-        TYPEINFO_INIT_CLASSINFO(*dst,comp->class);
-    }
-    else {
-        TYPEINFO_INIT_PRIMITIVE(*dst);
-    }
+       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
+                       TYPEINFO_INIT_PRIMITIVE(*dst);
+       }
+       else {
+               vftbl_t *comp;
+
+               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);
+               else
+                       TYPEINFO_INIT_PRIMITIVE(*dst);
+       }
     
-    dst->merged = srcarray->merged;
+    dst->merged = srcarray->merged; /* XXX should we do a deep copy? */
 }
 
 void
 typeinfo_clone(typeinfo *src,typeinfo *dest)
 {
     int count;
-    classinfo **srclist,**destlist;
+    classref_or_classinfo *srclist,*destlist;
 
     if (src == dest)
         return;
@@ -821,32 +896,29 @@ typeinfo_free(typeinfo *info)
 static
 void
 typeinfo_merge_error(char *str,typeinfo *x,typeinfo *y) {
-#ifdef TYPEINFO_DEBUG
+#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);
 #endif
-    panic(str);
+    panic(str); /* XXX throw an exception */
 }
 
 /* Condition: clsx != clsy. */
-/* Returns: true if dest was changed (always true). */
+/* Returns: true if dest was changed (currently always true). */
 static
 bool
-typeinfo_merge_two(typeinfo *dest,classinfo *clsx,classinfo *clsy)
+typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
 {
     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
     TYPEINFO_ALLOCMERGED(dest->merged,2);
     dest->merged->count = 2;
 
-#ifdef TYPEINFO_DEBUG
-    if (clsx == clsy)
-        panic("Internal error: typeinfo_merge_two called with clsx==clsy.");
-#endif
+       TYPEINFO_ASSERT(clsx.any != clsy.any);
 
-    if (clsx < clsy) {
+    if (clsx.any < clsy.any) {
         dest->merged->list[0] = clsx;
         dest->merged->list[1] = clsy;
     }
@@ -861,18 +933,18 @@ typeinfo_merge_two(typeinfo *dest,classinfo *clsx,classinfo *clsy)
 /* Returns: true if dest was changed. */
 static
 bool
-typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classinfo *cls)
+typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classref_or_classinfo cls)
 {
     int count;
     typeinfo_mergedlist *newmerged;
-    classinfo **mlist,**newlist;
+    classref_or_classinfo *mlist,*newlist;
 
     count = m->count;
     mlist = m->list;
 
     /* Check if cls is already in the mergedlist m. */
     while (count--) {
-        if (*mlist++ == cls) {
+        if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */
             /* cls is in the list, so m is the resulting mergedlist */
             if (dest->merged == m)
                 return false;
@@ -898,7 +970,7 @@ typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classinfo *cls)
     newlist = newmerged->list;    
     mlist = m->list;
     while (count) {
-        if (*mlist > cls)
+        if (mlist->any > cls.any)
             break;
         *newlist++ = *mlist++;
         count--;
@@ -924,7 +996,7 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
     int count = 0;
     int countx,county;
     typeinfo_mergedlist *temp,*result;
-    classinfo **clsx,**clsy,**newlist;
+    classref_or_classinfo *clsx,*clsy,*newlist;
 
     /* count the elements that will be in the resulting list */
     /* (Both lists are sorted, equal elements are counted only once.) */
@@ -933,13 +1005,13 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
     countx = x->count;
     county = y->count;
     while (countx && county) {
-        if (*clsx == *clsy) {
+        if (clsx->any == clsy->any) {
             clsx++;
             clsy++;
             countx--;
             county--;
         }
-        else if (*clsx < *clsy) {
+        else if (clsx->any < clsy->any) {
             clsx++;
             countx--;
         }
@@ -989,13 +1061,13 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
     countx = x->count;
     county = y->count;
     while (countx && county) {
-        if (*clsx == *clsy) {
+        if (clsx->any == clsy->any) {
             *newlist++ = *clsx++;
             clsy++;
             countx--;
             county--;
         }
-        else if (*clsx < *clsy) {
+        else if (clsx->any < clsy->any) {
             *newlist++ = *clsx++;
             countx--;
         }
@@ -1019,30 +1091,25 @@ typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
 static
 bool
 typeinfo_merge_nonarrays(typeinfo *dest,
-                         classinfo **result,
-                         classinfo *clsx,classinfo *clsy,
+                         classref_or_classinfo *result,
+                         classref_or_classinfo x,classref_or_classinfo y,
                          typeinfo_mergedlist *mergedx,
                          typeinfo_mergedlist *mergedy)
 {
+       classref_or_classinfo t;
     classinfo *tcls,*common;
     typeinfo_mergedlist *tmerged;
     bool changed;
+       utf *xname;
+       utf *yname;
 
-    /* DEBUG */
-    /*
-#ifdef TYPEINFO_DEBUG
-    typeinfo dbgx,dbgy;
-    printf("typeinfo_merge_nonarrays:\n");
-    TYPEINFO_INIT_CLASSINFO(dbgx,clsx);
-    dbgx.merged = mergedx;
-    TYPEINFO_INIT_CLASSINFO(dbgy,clsy);
-    dbgy.merged = mergedy;
-    typeinfo_print(stdout,&dbgx,4);
-    printf("  with:\n");
-    typeinfo_print(stdout,&dbgy,4);
-#endif
-    */ 
+       TYPEINFO_ASSERT(dest && result && x.any && y.any);
+       TYPEINFO_ASSERT(x.cls != pseudo_class_Null);
+       TYPEINFO_ASSERT(y.cls != pseudo_class_Null);
+       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))
@@ -1060,57 +1127,111 @@ typeinfo_merge_nonarrays(typeinfo *dest,
        if (!clsy->linked)
                if (!link_class(clsy))
                        return false;
+#endif
+
+       /*--------------------------------------------------*/
+       /* common cases                                     */
+       /*--------------------------------------------------*/
 
-    /* Common case: clsx == clsy */
+    /* Common case 1: x and y are the same class or class reference */
     /* (This case is very simple unless *both* x and y really represent
      *  merges of subclasses of clsx==clsy.)
      */
-    if ((clsx == clsy) && (!mergedx || !mergedy)) {
+    if ( (x.any == y.any) && (!mergedx || !mergedy) ) {
   return_simple_x:
         /* DEBUG */ /* log_text("return simple x"); */
         changed = (dest->merged != NULL);
         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
         dest->merged = NULL;
-        *result = clsx;
+        *result = x;
         /* DEBUG */ /* log_text("returning"); */
         return changed;
     }
-    
-    /* If clsy is an interface, swap x and y. */
-    if (clsy->flags & ACC_INTERFACE) {
-        tcls = clsx; clsx = clsy; clsy = tcls;
+
+       xname = (IS_CLASSREF(x)) ? x.ref->name : x.cls->name;
+       yname = (IS_CLASSREF(y)) ? y.ref->name : y.cls->name;
+
+       /* Common case 2: xname == yname, at least one unresolved */
+    if ((IS_CLASSREF(x) || IS_CLASSREF(y)) && (xname == yname))
+       {
+               /* use the loaded one if any */
+               if (!IS_CLASSREF(y))
+                       x = y;
+               goto return_simple_x;
+    }
+
+       /*--------------------------------------------------*/
+       /* non-trivial cases                                */
+       /*--------------------------------------------------*/
+
+#ifdef TYPEINFO_VERBOSE
+       {
+               typeinfo dbgx,dbgy;
+               fprintf(stderr,"merge_nonarrays:\n");
+               TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgx,x);
+               dbgx.merged = mergedx;
+               TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgy,y);
+               dbgy.merged = mergedy;
+               typeinfo_print(stderr,&dbgx,4);
+               fprintf(stderr,"  with:\n");
+               typeinfo_print(stderr,&dbgy,4);
+       }
+#endif
+
+    /* If y is unresolved or an interface, swap x and y. */
+    if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE))
+       {
+        t = x; x = y; y = t;
         tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
     }
+       
+    /* {We know: If only one of x,y is unresolved it is x,} */
+    /* {         If both x,y are resolved and only one of x,y is an interface it is x.} */
+
+       if (IS_CLASSREF(x)) {
+               /* {We know: x and y have different class names} */
+               
+        /* Check if we are merging an unresolved type with java.lang.Object */
+        if (y.cls == class_java_lang_Object && !mergedy) {
+            x = y;
+            goto return_simple_x;
+        }
+            
+               common = class_java_lang_Object;
+               goto merge_with_simple_x;
+       }
+
+       /* {We know: both x and y are resolved} */
     /* {We know: If only one of x,y is an interface it is x.} */
 
     /* Handle merging of interfaces: */
-    if (clsx->flags & ACC_INTERFACE) {
-        /* {clsx is an interface and mergedx == NULL.} */
+    if (x.cls->flags & ACC_INTERFACE) {
+        /* {x.cls is an interface and mergedx == NULL.} */
         
-        if (clsy->flags & ACC_INTERFACE) {
+        if (y.cls->flags & ACC_INTERFACE) {
             /* We are merging two interfaces. */
             /* {mergedy == NULL} */
 
-            /* {We know that clsx!=clsy (see common case at beginning.)} */
-            *result = class_java_lang_Object;
-            return typeinfo_merge_two(dest,clsx,clsy);
+            /* {We know that x.cls!=y.cls (see common case at beginning.)} */
+            result->cls = class_java_lang_Object;
+            return typeinfo_merge_two(dest,x,y);
         }
 
-        /* {We know: x is an interface, clsy is a class.} */
+        /* {We know: x is an interface, y is a class.} */
 
         /* Check if we are merging an interface with java.lang.Object */
-        if (clsy == class_java_lang_Object && !mergedy) {
-            clsx = clsy;
+        if (y.cls == class_java_lang_Object && !mergedy) {
+            x = y;
             goto return_simple_x;
         }
             
 
-        /* If the type y implements clsx then the result of the merge
-         * is clsx regardless of mergedy.
+        /* If the type y implements x then the result of the merge
+         * is x regardless of mergedy.
          */
         
-        if (CLASS_IMPLEMENTS_INTERFACE(clsy,clsx->index)
-            || mergedlist_implements_interface(mergedy,clsx))
+        if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index)
+            || mergedlist_implements_interface(mergedy,x.cls))
         {
             /* y implements x, so the result of the merge is x. */
             goto return_simple_x;
@@ -1120,7 +1241,7 @@ typeinfo_merge_nonarrays(typeinfo *dest,
          * of subclasses and does not implement x.} */
 
         /* There may still be superinterfaces of x which are implemented
-         * by y, too, so we have to add clsx to the mergedlist.
+         * 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 */
@@ -1132,16 +1253,16 @@ typeinfo_merge_nonarrays(typeinfo *dest,
     /* {We know: x and y are classes (not interfaces).} */
     
     /* If *x is deeper in the inheritance hierarchy swap x and y. */
-    if (clsx->index > clsy->index) {
-        tcls = clsx; clsx = clsy; clsy = tcls;
+    if (x.cls->index > y.cls->index) {
+        t = x; x = y; y = t;
         tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
     }
 
     /* {We know: y is at least as deep in the hierarchy as x.} */
 
     /* Find nearest common anchestor for the classes. */
-    common = clsx;
-    tcls = clsy;
+    common = x.cls;
+    tcls = y.cls;
     while (tcls->index > common->index)
         tcls = tcls->super;
     while (common != tcls) {
@@ -1149,29 +1270,29 @@ typeinfo_merge_nonarrays(typeinfo *dest,
         tcls = tcls->super;
     }
 
-    /* {common == nearest common anchestor of clsx and clsy.} */
+    /* {common == nearest common anchestor of x and y.} */
 
-    /* If clsx==common and x is a whole class (not a merge of subclasses)
-     * then the result of the merge is clsx.
+    /* If x.cls==common and x is a whole class (not a merge of subclasses)
+     * then the result of the merge is x.
      */
-    if (clsx == common && !mergedx) {
+    if (x.cls == common && !mergedx) {
         goto return_simple_x;
     }
    
     if (mergedx) {
-        *result = common;
+        result->cls = common;
         if (mergedy)
             return typeinfo_merge_mergedlists(dest,mergedx,mergedy);
         else
-            return typeinfo_merge_add(dest,mergedx,clsy);
+            return typeinfo_merge_add(dest,mergedx,y);
     }
 
- merge_with_simple_x:
-    *result = common;
+merge_with_simple_x:
+    result->cls = common;
     if (mergedy)
-        return typeinfo_merge_add(dest,mergedy,clsx);
+        return typeinfo_merge_add(dest,mergedy,x);
     else
-        return typeinfo_merge_two(dest,clsx,clsy);
+        return typeinfo_merge_two(dest,x,y);
 }
 
 /* Condition: *dest must be a valid initialized typeinfo. */
@@ -1181,41 +1302,36 @@ bool
 typeinfo_merge(typeinfo *dest,typeinfo* y)
 {
     typeinfo *x;
-    typeinfo *tmp;                      /* used for swapping */
-    classinfo *common;
-    classinfo *elementclass;
+    typeinfo *tmp;
+    classref_or_classinfo common;
+    classref_or_classinfo elementclass;
     int dimension;
     int elementtype;
     bool changed;
 
-    /* DEBUG */
-    /*
-#ifdef TYPEINFO_DEBUG
-    typeinfo_print(stdout,dest,4);
-    typeinfo_print(stdout,y,4);
-#endif
-    */
+       /*--------------------------------------------------*/
+       /* fast checks                                      */
+       /*--------------------------------------------------*/
 
     /* Merging something with itself is a nop */
     if (dest == y)
         return false;
 
     /* Merging two returnAddress types is ok. */
-    if (!dest->typeclass && !y->typeclass) {
-#ifdef TYPEINFO_DEBUG
-               if (TYPEINFO_RETURNADDRESS(*dest) != TYPEINFO_RETURNADDRESS(*y))
-                       panic("Internal error: typeinfo_merge merges different returnAddresses");
-#endif
+       /* Merging two different returnAddresses never happens, as the verifier */
+       /* keeps them separate in order to check all the possible return paths  */
+       /* from JSR subroutines.                                                */
+    if (!dest->typeclass.any && !y->typeclass.any) {
+               TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) ==  TYPEINFO_RETURNADDRESS(*y));
         return false;
        }
     
     /* Primitive types cannot be merged with reference types */
        /* XXX only check this in debug mode? */
-    if (!dest->typeclass || !y->typeclass)
+    if (!dest->typeclass.any || !y->typeclass.any)
         typeinfo_merge_error("Trying to merge primitive types.",dest,y);
 
     /* handle uninitialized object types */
-    /* XXX is there a way we could put this after the common case? */
     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);
@@ -1225,28 +1341,22 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
         return false;
     }
     
-    /* DEBUG */ /* log_text("Testing common case"); */
+       /*--------------------------------------------------*/
+       /* common cases                                     */
+       /*--------------------------------------------------*/
 
-    /* Common case: class dest == class y */
+    /* Common case: dest and y are the same class or class reference */
     /* (This case is very simple unless *both* dest and y really represent
      *  merges of subclasses of class dest==class y.)
      */
-    if ((dest->typeclass == y->typeclass) && (!dest->merged || !y->merged)) {
+    if ((dest->typeclass.any == y->typeclass.any) && (!dest->merged || !y->merged)) {
+return_simple:
         changed = (dest->merged != NULL);
-        TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* unify if? */
+        TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
         dest->merged = NULL;
-        /* DEBUG */ /* log_text("common case handled"); */
         return changed;
     }
     
-#ifdef TYPEINFO_DEBUG
-    /* check that no unlinked classes are merged. */
-    if (!dest->typeclass->linked || !y->typeclass->linked)
-        typeinfo_merge_error("Trying to merge unlinked class(es).",dest,y);
-#endif
-
-    /* DEBUG */ /* log_text("Handling null types"); */
-
     /* Handle null types: */
     if (TYPEINFO_IS_NULLTYPE(*y)) {
         return false;
@@ -1257,6 +1367,36 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
         return true;
     }
 
+       /* Common case: two types with the same name, at least one unresolved */
+       if (IS_CLASSREF(dest->typeclass)) {
+               if (IS_CLASSREF(y->typeclass)) {
+                       if (dest->typeclass.ref->name == y->typeclass.ref->name)
+                               goto return_simple;
+               }
+               else {
+                       /* XXX should we take y instead of dest here? */
+                       if (dest->typeclass.ref->name == y->typeclass.cls->name)
+                               goto return_simple;
+               }
+       }
+       else {
+               if (IS_CLASSREF(y->typeclass) 
+                   && (dest->typeclass.cls->name == y->typeclass.ref->name))
+               {
+                       goto return_simple;
+               }
+       }
+
+       /*--------------------------------------------------*/
+       /* non-trivial cases                                */
+       /*--------------------------------------------------*/
+
+#ifdef TYPEINFO_VERBOSE
+       fprintf(stderr,"merge:\n");
+    typeinfo_print(stderr,dest,4);
+    typeinfo_print(stderr,y,4);
+#endif
+
     /* This function uses x internally, so x and y can be swapped
      * without changing dest. */
     x = dest;
@@ -1265,8 +1405,6 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
     /* Handle merging of arrays: */
     if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
         
-        /* DEBUG */ /* log_text("Handling arrays"); */
-
         /* Make x the one with lesser dimension */
         if (x->dimension > y->dimension) {
             tmp = x; x = y; y = tmp;
@@ -1277,7 +1415,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
         if (x->dimension < y->dimension) {
             dimension = x->dimension;
             elementtype = ARRAYTYPE_OBJECT;
-            elementclass = pseudo_class_Arraystub;
+            elementclass.cls = pseudo_class_Arraystub;
         }
         else {
             dimension = y->dimension;
@@ -1291,14 +1429,14 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
             /* Different element types are merged, so the resulting array
              * type has one accessible dimension less. */
             if (--dimension == 0) {
-                common = pseudo_class_Arraystub;
+                common.cls = pseudo_class_Arraystub;
                 elementtype = 0;
-                elementclass = NULL;
+                elementclass.any = NULL;
             }
             else {
-                common = class_multiarray_of(dimension,pseudo_class_Arraystub);
+                common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub);
                 elementtype = ARRAYTYPE_OBJECT;
-                elementclass = pseudo_class_Arraystub;
+                elementclass.cls = pseudo_class_Arraystub;
             }
         }
         else {
@@ -1315,9 +1453,15 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
                                                     x->merged,y->merged);
 
                 /* DEBUG */ /* log_text("finding resulting array class: "); */
-                common = class_multiarray_of(dimension,elementclass);
+                               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.any = y->typeclass.any;
+                       }
         }
     }
     else {
@@ -1331,13 +1475,13 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
 
         dimension = 0;
         elementtype = 0;
-        elementclass = NULL;
+        elementclass.any = NULL;
     }
 
     /* Put the new values into dest if neccessary. */
 
-    if (dest->typeclass != common) {
-        dest->typeclass = common;
+    if (dest->typeclass.any != common.any) {
+        dest->typeclass.any = common.any;
         changed = true;
     }
     if (dest->dimension != dimension) {
@@ -1348,13 +1492,11 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
         dest->elementtype = elementtype;
         changed = true;
     }
-    if (dest->elementclass != elementclass) {
-        dest->elementclass = elementclass;
+    if (dest->elementclass.any != elementclass.any) {
+        dest->elementclass.any = elementclass.any;
         changed = true;
     }
 
-    /* DEBUG */ /* log_text("returning from merge"); */
-    
     return changed;
 }
 
@@ -1365,17 +1507,15 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
 
 #ifdef TYPEINFO_DEBUG
 
-
-/*extern instruction *instr;*/
-
 static int
-typeinfo_test_compare(classinfo **a,classinfo **b)
+typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
 {
-    if (*a == *b) return 0;
-    if (*a < *b) return -1;
+    if (a->any == b->any) return 0;
+    if (a->any < b->any) return -1;
     return +1;
 }
 
+#if 0
 static void
 typeinfo_test_parse(typeinfo *info,char *str)
 {
@@ -1400,9 +1540,9 @@ typeinfo_test_parse(typeinfo *info,char *str)
         for (i=0; i<num; ++i) {
             if (typebuf[i] != TYPE_ADDRESS)
                 panic("non-reference type in mergedlist");
-            info->merged->list[i] = infobuf[i].typeclass;
+            info->merged->list[i].any = infobuf[i].typeclass.any;
         }
-        qsort(info->merged->list,num,sizeof(classinfo*),
+        qsort(info->merged->list,num,sizeof(classref_or_classinfo),
               (int(*)(const void *,const void *))&typeinfo_test_compare);
     }
     else {
@@ -1410,6 +1550,7 @@ typeinfo_test_parse(typeinfo *info,char *str)
                                        &returntype,info);
     }
 }
+#endif
 
 #define TYPEINFO_TEST_BUFLEN  4000
 
@@ -1418,10 +1559,10 @@ typeinfo_equal(typeinfo *x,typeinfo *y)
 {
     int i;
     
-    if (x->typeclass != y->typeclass) return false;
+    if (x->typeclass.any != y->typeclass.any) return false;
     if (x->dimension != y->dimension) return false;
     if (x->dimension) {
-        if (x->elementclass != y->elementclass) return false;
+        if (x->elementclass.any != y->elementclass.any) return false;
         if (x->elementtype != y->elementtype) return false;
     }
 
@@ -1434,7 +1575,7 @@ typeinfo_equal(typeinfo *x,typeinfo *y)
         if (!(x->merged && y->merged)) return false;
         if (x->merged->count != y->merged->count) return false;
         for (i=0; i<x->merged->count; ++i)
-            if (x->merged->list[i] != y->merged->list[i])
+            if (x->merged->list[i].any != y->merged->list[i].any)
                 return false;
     }
     return true;
@@ -1479,6 +1620,7 @@ typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
     }
 }
 
+#if 0
 static void
 typeinfo_inc_dimension(typeinfo *info)
 {
@@ -1488,6 +1630,7 @@ typeinfo_inc_dimension(typeinfo *info)
     }
     info->typeclass = class_array_of(info->typeclass);
 }
+#endif
 
 #define TYPEINFO_TEST_MAXDIM  10
 
@@ -1514,11 +1657,14 @@ typeinfo_testrun(char *filename)
         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 0
         typeinfo_test_parse(&a,bufa);
         typeinfo_test_parse(&b,bufb);
         typeinfo_test_parse(&c,bufc);
+#endif
+#if 0
         do {
+#endif
             typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
             typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
 
@@ -1530,12 +1676,14 @@ typeinfo_testrun(char *filename)
             if (b.dimension > maxdim) maxdim = b.dimension;
             if (c.dimension > maxdim) maxdim = c.dimension;
 
+#if 0
             if (maxdim < TYPEINFO_TEST_MAXDIM) {
                 typeinfo_inc_dimension(&a);
                 typeinfo_inc_dimension(&b);
                 typeinfo_inc_dimension(&c);
             }
         } while (maxdim < TYPEINFO_TEST_MAXDIM);
+#endif
     }
 
     fclose(file);
@@ -1554,14 +1702,35 @@ typeinfo_test()
     log_text("Finished typeinfo test file.");
 }
 
+#if 0
 void
 typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
 {
     typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
 }
+#endif
 
 #define TYPEINFO_MAXINDENT  80
 
+void
+typeinfo_print_class(FILE *file,classref_or_classinfo c)
+{
+       /*fprintf(file,"<class %p>",c.any);*/
+
+       if (!c.any) {
+               fprintf(file,"<null>");
+       }
+       else {
+               if (IS_CLASSREF(c)) {
+                       fprintf(file,"<ref>");
+                       utf_fprint(file,c.ref->name);
+               }
+               else {
+                       utf_fprint(file,c.cls->name);
+               }
+       }
+}
+
 void
 typeinfo_print(FILE *file,typeinfo *info,int indent)
 {
@@ -1593,8 +1762,8 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
     if (TYPEINFO_IS_NEWOBJECT(*info)) {
         ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
         if (ins) {
-            fprintf(file,"%sNEW(%d):",ind,ins-bptr->iinstr);
-            utf_fprint(file,((classinfo *)ins[-1].val.a)->name);
+            fprintf(file,"%sNEW(%p):",ind,ins);
+                       typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
             fprintf(file,"\n");
         }
         else {
@@ -1604,7 +1773,7 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
     }
 
     fprintf(file,"%sClass:      ",ind);
-    utf_fprint(file,info->typeclass->name);
+       typeinfo_print_class(file,info->typeclass);
     fprintf(file,"\n");
 
     if (TYPEINFO_IS_ARRAY(*info)) {
@@ -1621,8 +1790,7 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
           case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
               
           case ARRAYTYPE_OBJECT:
-              fprintf(file,"reference: ");
-              utf_fprint(file,info->elementclass->name);
+                         typeinfo_print_class(file,info->elementclass);
               fprintf(file,"\n");
               break;
               
@@ -1632,10 +1800,10 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
     }
 
     if (info->merged) {
-        fprintf(file,"%sMerged: ",ind);
+        fprintf(file,"%sMerged:     ",ind);
         for (i=0; i<info->merged->count; ++i) {
             if (i) fprintf(file,", ");
-            utf_fprint(file,info->merged->list[i]->name);
+                       typeinfo_print_class(file,info->merged->list[i]);
         }
         fprintf(file,"\n");
     }
@@ -1647,6 +1815,14 @@ typeinfo_print_short(FILE *file,typeinfo *info)
     int i;
     instruction *ins;
        basicblock *bptr;
+       classref_or_classinfo c;
+
+       /*fprintf(file,"<typeinfo %p>",info);*/
+
+       if (!info) {
+               fprintf(file,"(typeinfo*)NULL");
+               return;
+       }
 
     if (TYPEINFO_IS_PRIMITIVE(*info)) {
                bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
@@ -1665,21 +1841,22 @@ typeinfo_print_short(FILE *file,typeinfo *info)
     if (TYPEINFO_IS_NEWOBJECT(*info)) {
         ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
         if (ins) {
-            fprintf(file,"NEW(%d):",ins-bptr->iinstr);
-            utf_fprint(file,((classinfo *)ins[-1].val.a)->name);
+                       /*fprintf(file,"<ins %p>",ins);*/
+            fprintf(file,"NEW(%p):",ins);
+                       typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
         }
         else
             fprintf(file,"NEW(this)");
         return;
     }
 
-    utf_fprint(file,info->typeclass->name);
+    typeinfo_print_class(file,info->typeclass);
 
     if (info->merged) {
         fprintf(file,"{");
         for (i=0; i<info->merged->count; ++i) {
             if (i) fprintf(file,",");
-            utf_fprint(file,info->merged->list[i]->name);
+                       typeinfo_print_class(file,info->merged->list[i]);
         }
         fprintf(file,"}");
     }
@@ -1706,6 +1883,8 @@ 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);
index 3e69cbe3c9dedd6cce224a720475b0d27780d9ab..4601b56db42c29d2d34282f3ea70799a26c04e3b 100644 (file)
 
    Authors: Edwin Steiner
 
-   $Id: typeinfo.h 2087 2005-03-25 20:14:29Z edwin $
+   $Id: typeinfo.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
-
 #ifndef _TYPEINFO_H
 #define _TYPEINFO_H
 
 #include "vm/global.h"
+#include "vm/references.h"
+
+/* configuration **************************************************************/
+
+/*
+ * TYPECHECK_STATISTICS activates gathering statistical information.
+ * TYPEINFO_DEBUG activates debug checks and debug helpers in typeinfo.c
+ * TYPECHECK_DEBUG activates debug checks in typecheck.c
+ * TYPEINFO_DEBUG_TEST activates the typeinfo test at startup.
+ * TYPECHECK_VERBOSE_IMPORTANT activates important debug messages
+ * TYPECHECK_VERBOSE activates all debug messages
+ * TYPEINFO_VERBOSE activates debug prints in typeinfo.c
+ */
+#ifdef CACAO_TYPECHECK
+/*#define TYPECHECK_STATISTICS*/
+#define TYPEINFO_DEBUG
+/*#define TYPEINFO_VERBOSE*/
+#define TYPECHECK_DEBUG
+/*#define TYPEINFO_DEBUG_TEST
+#define TYPECHECK_VERBOSE
+#define TYPECHECK_VERBOSE_IMPORTANT*/
+#if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
+#define TYPECHECK_VERBOSE_OPT
+#endif
+#endif
+
+#ifdef TYPECHECK_VERBOSE_OPT
+extern bool typecheckverbose;
+#endif
 
 /* resolve typedef cycles *****************************************************/
 
@@ -44,6 +72,22 @@ typedef struct typedescriptor typedescriptor;
 typedef struct typevector typevector;
 typedef struct typeinfo_retaddr_set typeinfo_retaddr_set;
 
+/* constants ******************************************************************/
+
+#define MAYBE  2
+
+#if MAYBE == true
+#error "`MAYBE` must not be the same as `true`"
+#endif
+#if MAYBE == false
+#error "`MAYBE` must not be the same as `false`"
+#endif
+
+/* types **********************************************************************/
+
+/* a tristate_t is one of {true,false,MAYBE} */
+typedef int tristate_t;
+
 /* data structures for the type system ****************************************/
 
 /* The typeinfo structure stores detailed information on address types.
@@ -132,45 +176,45 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set;
  *        1) pseudo_class_Arraystub
  *        2) an unresolved type
  *        3) a loaded interface
- *        4) a loaded (non-pseudo-,non-array-)class != java.lang.Object
+ *        4) a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
  *                Note: `merged` may be used
- *        5) java.lang.Object
+ *        5) (BOOTSTRAP)java.lang.Object
  *                Note: `merged` may be used
  *
  *        For the semantics of the merged field in cases 4) and 5) consult the 
  *        corresponding descriptions with `elementclass` replaced by `typeclass`.
  *
- * X) typeclass is an unresolved type (a symbolic class/interface reference)
+ * F) typeclass is an unresolved type (a symbolic class/interface reference)
  *
  *        The type has not been resolved yet. (Meaning it corresponds to an
  *        unloaded class or interface).
  *        Don't access other fields of the struct.
  *
- * F) typeclass is a loaded interface
+ * G) typeclass is a loaded interface
  *
  *        An interface reference type.
  *        Don't access other fields of the struct.
  *
- * G) typeclass is a loaded (non-pseudo-,non-array-)class != java.lang.Object
+ * H) typeclass is a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
  *
  *        A loaded class type.
- *        All classinfos in u.merged.list (if any) are
+ *        All classref_or_classinfos in u.merged.list (if any) are
  *        loaded subclasses of typeclass (no interfaces, array classes, or
  *        unresolved types).
  *        Don't access other fields of the struct.
  *
- * H) typeclass is (BOOTSTRAP)java.lang.Object
+ * I) typeclass is (BOOTSTRAP)java.lang.Object
  *
  *        The most general kind of reference type.
  *        In this case u.merged.count and u.merged.list
  *        are valid and may be non-zero.
- *        The classinfos in u.merged.list (if any) may be
+ *        The classref_or_classinfos in u.merged.list (if any) may be
  *        classes, interfaces, pseudo classes or unresolved types.
  *        Don't access other fields of the struct.
  */
 
 /* The following algorithm is used to determine if the type described
- * by this typeinfo struct supports the interface X:
+ * by this typeinfo struct supports the interface X:  * XXX add MAYBE *
  *
  *     1) If typeclass is X or a subinterface of X the answer is "yes".
  *     2) If typeclass is a (pseudo) class implementing X the answer is "yes".
@@ -186,16 +230,16 @@ typedef struct typeinfo_retaddr_set typeinfo_retaddr_set;
  *          access typeinfo structures!
  */
 struct typeinfo {
-       classinfo           *typeclass;
-       classinfo           *elementclass; /* valid if dimension>0 */ /* various uses! */
-       typeinfo_mergedlist *merged;
-       u1                   dimension;
-       u1                   elementtype;  /* valid if dimension>0           */
+       classref_or_classinfo  typeclass;
+       classref_or_classinfo  elementclass; /* valid if dimension>0 */ /* various uses! */
+       typeinfo_mergedlist   *merged;
+       u1                     dimension;
+       u1                     elementtype;  /* valid if dimension>0           */
 };
 
 struct typeinfo_mergedlist {
-       s4         count;
-       classinfo *list[1];       /* variable length!                        */
+       s4                    count;
+       classref_or_classinfo list[1];       /* variable length!                        */
 };
 
 /*-----------------------------------------------------------------------*/
@@ -287,24 +331,24 @@ struct typevector {
 /* macros for type queries **************************************************/
 
 #define TYPEINFO_IS_PRIMITIVE(info)                             \
-            ((info).typeclass == NULL)
+            ((info).typeclass.any == NULL)
 
 #define TYPEINFO_IS_REFERENCE(info)                             \
-            ((info).typeclass != NULL)
+            ((info).typeclass.any != NULL)
 
 #define TYPEINFO_IS_NULLTYPE(info)                              \
-            ((info).typeclass == pseudo_class_Null)
+            ((info).typeclass.cls == pseudo_class_Null)
 
 #define TYPEINFO_IS_NEWOBJECT(info)                             \
-            ((info).typeclass == pseudo_class_New)
+            ((info).typeclass.cls == pseudo_class_New)
 
 /* only use this if TYPEINFO_IS_PRIMITIVE returned true! */
 #define TYPEINFO_RETURNADDRESS(info)                            \
-            ((void *)(info).elementclass)
+            ((void *)(info).elementclass.any)
 
 /* only use this if TYPEINFO_IS_NEWOBJECT returned true! */
 #define TYPEINFO_NEWOBJECT_INSTRUCTION(info)                    \
-            ((void *)(info).elementclass)
+            ((void *)(info).elementclass.any)
 
 /* macros for array type queries ********************************************/
 
@@ -324,11 +368,11 @@ struct typevector {
 
 #define TYPEINFO_IS_OBJECT_ARRAY(info)                          \
             ( TYPEINFO_IS_SIMPLE_ARRAY(info)                    \
-              && ((info).elementclass != NULL) )
+              && ((info).elementclass.any != NULL) )
 
 /* assumes that info describes an array type */
 #define TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info)                 \
-            ( ((info).elementclass != NULL)                     \
+            ( ((info).elementclass.any != NULL)                 \
               || ((info).dimension >= 2) )
 
 #define TYPEINFO_IS_ARRAY_OF_REFS(info)                         \
@@ -363,22 +407,22 @@ struct typevector {
 /* macros for initializing typeinfo structures ******************************/
 
 #define TYPEINFO_INIT_PRIMITIVE(info)                           \
-         do {(info).typeclass = NULL;                           \
-             (info).elementclass = NULL;                        \
+         do {(info).typeclass.any = NULL;                       \
+             (info).elementclass.any = NULL;                    \
              (info).merged = NULL;                              \
              (info).dimension = 0;                              \
              (info).elementtype = 0;} while(0)
 
 #define TYPEINFO_INIT_RETURNADDRESS(info,adr)                   \
-         do {(info).typeclass = NULL;                           \
-             (info).elementclass = (classinfo*) (adr);          \
+         do {(info).typeclass.any = NULL;                       \
+             (info).elementclass.any = (adr);                   \
              (info).merged = NULL;                              \
              (info).dimension = 0;                              \
              (info).elementtype = 0;} while(0)
 
 #define TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,cinfo)   \
-         do {(info).typeclass = (cinfo);                \
-             (info).elementclass = NULL;                \
+         do {(info).typeclass.cls = (cinfo);            \
+             (info).elementclass.any = NULL;            \
              (info).merged = NULL;                      \
              (info).dimension = 0;                      \
              (info).elementtype = 0;} while(0)
@@ -387,8 +431,8 @@ struct typevector {
             TYPEINFO_INIT_CLASSINFO(info,pseudo_class_Null)
 
 #define TYPEINFO_INIT_NEWOBJECT(info,instr)             \
-         do {(info).typeclass = pseudo_class_New;       \
-             (info).elementclass = (classinfo*) (instr);\
+         do {(info).typeclass.cls = pseudo_class_New;   \
+             (info).elementclass.any = (instr);         \
              (info).merged = NULL;                      \
              (info).dimension = 0;                      \
              (info).elementtype = 0;} while(0)
@@ -396,25 +440,27 @@ struct typevector {
 #define TYPEINFO_INIT_PRIMITIVE_ARRAY(info,arraytype)                   \
     TYPEINFO_INIT_CLASSINFO(info,primitivetype_table[arraytype].arrayclass);
 
-#define TYPEINFO_INIT_CLASSINFO(info,cls)                               \
-        do {if (((info).typeclass = (cls))->vftbl->arraydesc) {         \
-                if ((cls)->vftbl->arraydesc->elementvftbl)              \
-                    (info).elementclass = (cls)->vftbl->arraydesc->elementvftbl->class; \
+#define TYPEINFO_INIT_CLASSINFO(info,c)                                 \
+        do {if (((info).typeclass.cls = (c))->vftbl->arraydesc) {       \
+                if ((c)->vftbl->arraydesc->elementvftbl)                \
+                    (info).elementclass.cls = (c)->vftbl->arraydesc->elementvftbl->class; \
                 else                                                    \
-                    (info).elementclass = NULL;                         \
-                (info).dimension = (cls)->vftbl->arraydesc->dimension;  \
-                (info).elementtype = (cls)->vftbl->arraydesc->elementtype; \
+                    (info).elementclass.any = NULL;                     \
+                (info).dimension = (c)->vftbl->arraydesc->dimension;    \
+                (info).elementtype = (c)->vftbl->arraydesc->elementtype;\
             }                                                           \
             else {                                                      \
-                (info).elementclass = NULL;                             \
+                (info).elementclass.any = NULL;                         \
                 (info).dimension = 0;                                   \
                 (info).elementtype = 0;                                 \
             }                                                           \
             (info).merged = NULL;} while(0)
 
-#define TYPEINFO_INIT_FROM_FIELDINFO(info,fi)                   \
-            typeinfo_init_from_descriptor(&(info),              \
-                (fi)->descriptor->text,utf_end((fi)->descriptor));
+#define TYPEINFO_INIT_CLASSREF(info,c)    \
+            typeinfo_init_class(&(info),CLASSREF_OR_CLASSINFO(c))
+
+#define TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(info,c)    \
+            typeinfo_init_class(&(info),c)
 
 /* macros for copying types (destinition is not checked or freed) ***********/
 
@@ -447,7 +493,7 @@ int typevectorset_mergedtype(typevector *set,int index,typeinfo *temp,typeinfo *
 void typevectorset_store(typevector *set,int index,int type,typeinfo *info);
 void typevectorset_store_retaddr(typevector *set,int index,typeinfo *info);
 void typevectorset_store_twoword(typevector *set,int index,int type);
-void typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,int size);
+void typevectorset_init_object(typevector *set,void *ins,classref_or_classinfo initclass,int size);
 
 /* vector functions */
 bool typevector_separable_from(typevector *a,typevector *b,int size);
@@ -466,31 +512,35 @@ bool typeinfo_is_array(typeinfo *info);
 bool typeinfo_is_primitive_array(typeinfo *info,int arraytype);
 bool typeinfo_is_array_of_refs(typeinfo *info);
 
-bool typeinfo_implements_interface(typeinfo *info,classinfo *interf);
-bool typeinfo_is_assignable(typeinfo *value,typeinfo *dest);
-bool typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest);
+tristate_t typeinfo_implements_interface(typeinfo *info,classinfo *interf);
+tristate_t typeinfo_is_assignable(typeinfo *value,typeinfo *dest);
+tristate_t typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest);
 
 /* initialization functions *************************************************/
 
-void typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr);
+bool typeinfo_init_class(typeinfo *info,classref_or_classinfo c);
 void typeinfo_init_component(typeinfo *srcarray,typeinfo *dst);
 
-int  typeinfo_count_method_args(utf *d,bool twoword); /* this not included */
-void typeinfo_init_from_method_args(utf *desc,u1 *typebuf,
-                                    typeinfo *infobuf,
-                                    int buflen,bool twoword,
-                                    int *returntype,typeinfo *returntypeinfo);
-int  typedescriptors_init_from_method_args(typedescriptor *td,
-                                                                                  utf *desc,
-                                                                                  int buflen,bool twoword,
-                                                                                  typedescriptor *returntype);
+void typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info);
+void typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,
+                                   typeinfo *infobuf,
+                                   int buflen,bool twoword,
+                                   u1 *returntype,typeinfo *returntypeinfo);
+void  typedescriptor_init_from_typedesc(typedescriptor *td,
+                                                                           typedesc *desc);
+int  typedescriptors_init_from_methoddesc(typedescriptor *td,
+                                                                                 methoddesc *desc,
+                                                                                 int buflen,bool twoword,
+                                                                                 typedescriptor *returntype);
 
 void typeinfo_clone(typeinfo *src,typeinfo *dest);
 
-/* functions for the type system ********************************************/
+/* freeing memory ***********************************************************/
 
 void typeinfo_free(typeinfo *info);
 
+/* functions for merging types **********************************************/
+
 bool typeinfo_merge(typeinfo *dest,typeinfo* y);
 
 /* debugging helpers ********************************************************/
@@ -500,7 +550,7 @@ bool typeinfo_merge(typeinfo *dest,typeinfo* y);
 #include <stdio.h>
 
 void typeinfo_test();
-void typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc);
+void typeinfo_print_class(FILE *file,classref_or_classinfo c);
 void typeinfo_print(FILE *file,typeinfo *info,int indent);
 void typeinfo_print_short(FILE *file,typeinfo *info);
 void typeinfo_print_type(FILE *file,int type,typeinfo *info);
index 4ff12a5ac238ac2e9e95e413b1309f8f8cb05adb..cb89bcf35bffbdc4d08f3bb516299c980f66e3fc 100644 (file)
@@ -32,7 +32,7 @@
             Edwin Steiner
             Christian Thalinger
 
-   $Id: linker.c 2169 2005-03-31 15:50:57Z twisti $
+   $Id: linker.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -975,6 +975,43 @@ static s4 class_highestinterface(classinfo *c)
 }
 
 
+/***************** Function: print_arraydescriptor ****************************
+
+       Debugging helper for displaying an arraydescriptor
+       
+*******************************************************************************/
+
+void print_arraydescriptor(FILE *file, arraydescriptor *desc)
+{
+       if (!desc) {
+               fprintf(file, "<NULL>");
+               return;
+       }
+
+       fprintf(file, "{");
+       if (desc->componentvftbl) {
+               if (desc->componentvftbl->class)
+                       utf_fprint(file, desc->componentvftbl->class->name);
+               else
+                       fprintf(file, "<no classinfo>");
+       }
+       else
+               fprintf(file, "0");
+               
+       fprintf(file, ",");
+       if (desc->elementvftbl) {
+               if (desc->elementvftbl->class)
+                       utf_fprint(file, desc->elementvftbl->class->name);
+               else
+                       fprintf(file, "<no classinfo>");
+       }
+       else
+               fprintf(file, "0");
+       fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
+                       desc->dataoffset, desc->componentsize);
+}
+
+
 /*
  * 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
index cd77fcec4474e0c2ef8eff0dac7228dfb9438eb4..44e10dc54401fa4e47b178d684cdc60c90851d83 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: linker.h 2148 2005-03-30 16:49:40Z twisti $
+   $Id: linker.h 2181 2005-04-01 16:53:33Z edwin $
 */
 
 
@@ -42,7 +42,7 @@ typedef struct arraydescriptor arraydescriptor;
 typedef struct primitivetypeinfo primitivetypeinfo;
 
 
-#include "vm/class.h"
+#include "vm/references.h"
 
 
 /* virtual function table ******************************************************
@@ -163,6 +163,9 @@ extern primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT];
 bool linker_init(void);
 classinfo *link_class(classinfo *c);
 
+/* debug print arraydescriptor */
+void print_arraydescriptor(FILE *file, arraydescriptor *desc);
+
 #endif /* _LINKER_H */
 
 
index aad9a25a9e4866fbd0e6d9ee1472ccdb915f8dc9..fb7233f75fbfc013c9d662ddbfa55d3d6d2eb5b5 100644 (file)
@@ -32,7 +32,7 @@
             Edwin Steiner
             Christian Thalinger
 
-   $Id: loader.c 2155 2005-03-30 20:04:42Z twisti $
+   $Id: loader.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -927,7 +927,7 @@ u4 class_constanttype(classinfo *c, u4 pos)
 
 *******************************************************************************/
 
-static bool load_constantpool(classbuffer *cb)
+static bool load_constantpool(classbuffer *cb,descriptor_pool *descpool)
 {
 
        /* The following structures are used to save information which cannot be 
@@ -1227,6 +1227,18 @@ static bool load_constantpool(classbuffer *cb)
                }  /* end switch */
        } /* end while */
 
+       /* add all class references to the descriptor_pool */
+       for (nfc=forward_classes; nfc; nfc=nfc->next) {
+               utf *name = class_getconstant(c,nfc->name_index,CONSTANT_Utf8);
+               if (!descriptor_pool_add_class(descpool,name))
+                       return false;
+       }
+       /* add all descriptors in NameAndTypes to the descriptor_pool */
+       for (nfn=forward_nameandtypes; nfn; nfn=nfn->next) {
+               utf *desc = class_getconstant(c,nfn->sig_index,CONSTANT_Utf8);
+               if (!descriptor_pool_add(descpool,desc))
+                       return false;
+       }
 
        /* resolve entries in temporary structures */
 
@@ -1373,7 +1385,7 @@ static bool load_constantpool(classbuffer *cb)
 
 #define field_load_NOVALUE  0xffffffff /* must be bigger than any u2 value! */
 
-static bool load_field(classbuffer *cb, fieldinfo *f)
+static bool load_field(classbuffer *cb, fieldinfo *f,descriptor_pool *descpool)
 {
        classinfo *c;
        u4 attrnum, i;
@@ -1395,6 +1407,9 @@ static bool load_field(classbuffer *cb, fieldinfo *f)
        if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                return false;
        f->descriptor = u;
+       f->parseddesc = NULL;
+       if (!descriptor_pool_add(descpool,u))
+               return false;
 
        if (opt_verify) {
                /* check name */
@@ -1561,7 +1576,7 @@ static bool load_field(classbuffer *cb, fieldinfo *f)
        
 *******************************************************************************/
 
-static bool load_method(classbuffer *cb, methodinfo *m)
+static bool load_method(classbuffer *cb, methodinfo *m,descriptor_pool *descpool)
 {
        classinfo *c;
        s4 argcount;
@@ -1599,6 +1614,9 @@ static bool load_method(classbuffer *cb, methodinfo *m)
        if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
                return false;
        m->descriptor = u;
+       m->parseddesc = NULL;
+       if (!descriptor_pool_add(descpool,u))
+               return false;
 
        if (opt_verify) {
                if (!is_valid_name_utf(m->name))
@@ -1966,43 +1984,6 @@ static bool load_attributes(classbuffer *cb, u4 num)
 }
 
 
-/***************** Function: print_arraydescriptor ****************************
-
-       Debugging helper for displaying an arraydescriptor
-       
-*******************************************************************************/
-
-void print_arraydescriptor(FILE *file, arraydescriptor *desc)
-{
-       if (!desc) {
-               fprintf(file, "<NULL>");
-               return;
-       }
-
-       fprintf(file, "{");
-       if (desc->componentvftbl) {
-               if (desc->componentvftbl->class)
-                       utf_fprint(file, desc->componentvftbl->class->name);
-               else
-                       fprintf(file, "<no classinfo>");
-       }
-       else
-               fprintf(file, "0");
-               
-       fprintf(file, ",");
-       if (desc->elementvftbl) {
-               if (desc->elementvftbl->class)
-                       utf_fprint(file, desc->elementvftbl->class->name);
-               else
-                       fprintf(file, "<no classinfo>");
-       }
-       else
-               fprintf(file, "0");
-       fprintf(file, ",%d,%d,%d,%d}", desc->arraytype, desc->dimension,
-                       desc->dataoffset, desc->componentsize);
-}
-
-
 /* load_class_from_classloader *************************************************
 
    XXX
@@ -2150,7 +2131,13 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        classinfo *tc;
        u4 i;
        u4 ma, mi;
+       s4 dumpsize;
+       descriptor_pool *descpool;
        char msg[MAXLOGTEXT];               /* maybe we get an exception */
+#if defined(STATISTICS)
+       u4 classrefsize;
+       u4 descsize;
+#endif
 
        /* get the classbuffer's class */
        c = cb->class;
@@ -2168,17 +2155,20 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
        if (loadverbose)
                log_message_class("Loading class: ", c);
        
+       /* mark start of dump memory area */
+       dumpsize = dump_size();
+
        /* class is somewhat loaded */
        c->loaded = true;
 
        if (!check_classbuffer_size(cb, 4 + 2 + 2))
-               return NULL;
+               goto return_exception;
 
        /* check signature */
        if (suck_u4(cb) != MAGIC) {
                *exceptionptr = new_classformaterror(c, "Bad magic number");
 
-               return NULL;
+               goto return_exception;
        }
 
        /* check version */
@@ -2191,12 +2181,15 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                                                                         "Unsupported major.minor version %d.%d",
                                                                                         ma, mi);
 
-               return NULL;
+               goto return_exception;
        }
 
+       /* create a new descriptor pool */
+       descpool = descriptor_pool_new(c);
+       
        /* load the constant pool */
-       if (!load_constantpool(cb))
-               return NULL;
+       if (!load_constantpool(cb,descpool))
+               goto return_exception;
 
        /*JOWENN*/
        c->erroneous_state = 0;
@@ -2207,7 +2200,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
        /* ACC flags */
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        c->flags = suck_u2(cb);
        /*if (!(c->flags & ACC_PUBLIC)) { log_text("CLASS NOT PUBLIC"); } JOWENN*/
@@ -2227,7 +2220,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                new_classformaterror(c,
                                                                         "Illegal class modifiers: 0x%X", c->flags);
 
-                       return NULL;
+                       goto return_exception;
                }
 
                if (c->flags & ACC_SUPER) {
@@ -2239,16 +2232,16 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                *exceptionptr =
                        new_classformaterror(c, "Illegal class modifiers: 0x%X", c->flags);
 
-               return NULL;
+               goto return_exception;
        }
 
        if (!check_classbuffer_size(cb, 2 + 2))
-               return NULL;
+               goto return_exception;
 
        /* this class */
        i = suck_u2(cb);
        if (!(tc = class_getconstant(c, i, CONSTANT_Class)))
-               return NULL;
+               goto return_exception;
 
        if (tc != c) {
                utf_sprint(msg, c->name);
@@ -2259,13 +2252,13 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                *exceptionptr =
                        new_exception_message(string_java_lang_NoClassDefFoundError, msg);
 
-               return NULL;
+               goto return_exception;
        }
        
        /* retrieve superclass */
        if ((i = suck_u2(cb))) {
                if (!(c->super = class_getconstant(c, i, CONSTANT_Class)))
-                       return NULL;
+                       goto return_exception;
 
                /* java.lang.Object may not have a super class. */
                if (c->name == utf_java_lang_Object) {
@@ -2273,7 +2266,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                new_exception_message(string_java_lang_ClassFormatError,
                                                                          "java.lang.Object with superclass");
 
-                       return NULL;
+                       goto return_exception;
                }
 
                /* Interfaces must have java.lang.Object as super class. */
@@ -2283,7 +2276,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                new_exception_message(string_java_lang_ClassFormatError,
                                                                          "Interfaces must have java.lang.Object as superclass");
 
-                       return NULL;
+                       goto return_exception;
                }
 
        } else {
@@ -2293,47 +2286,100 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                if (c->name != utf_java_lang_Object) {
                        *exceptionptr = new_classformaterror(c, "Bad superclass index");
 
-                       return NULL;
+                       goto return_exception;
                }
        }
                         
        /* retrieve interfaces */
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        c->interfacescount = suck_u2(cb);
 
        if (!check_classbuffer_size(cb, 2 * c->interfacescount))
-               return NULL;
+               goto return_exception;
 
        c->interfaces = MNEW(classinfo*, c->interfacescount);
        for (i = 0; i < c->interfacescount; i++) {
                if (!(c->interfaces[i] = class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
-                       return NULL;
+                       goto return_exception;
        }
 
        /* load fields */
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        c->fieldscount = suck_u2(cb);
        c->fields = GCNEW(fieldinfo, c->fieldscount);
 /*     c->fields = MNEW(fieldinfo, c->fieldscount); */
        for (i = 0; i < c->fieldscount; i++) {
-               if (!load_field(cb, &(c->fields[i])))
-                       return NULL;
+               if (!load_field(cb, &(c->fields[i]),descpool))
+                       goto return_exception;
        }
 
        /* load methods */
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        c->methodscount = suck_u2(cb);
 /*     c->methods = GCNEW(methodinfo, c->methodscount); */
        c->methods = MNEW(methodinfo, c->methodscount);
        for (i = 0; i < c->methodscount; i++) {
-               if (!load_method(cb, &(c->methods[i])))
-                       return NULL;
+               if (!load_method(cb, &(c->methods[i]),descpool))
+                       goto return_exception;
+       }
+
+       /* create the class reference table */
+       c->classrefs = descriptor_pool_create_classrefs(descpool,&(c->classrefcount));
+
+       /* allocate space for the parsed descriptors */
+       descriptor_pool_alloc_parsed_descriptors(descpool);
+       c->parseddescs = descriptor_pool_get_parsed_descriptors(descpool,&(c->parseddescsize));
+
+#if defined(STATISTICS)
+       if (opt_stat) {
+               descriptor_pool_get_sizes(descpool,&classrefsize,&descsize);
+               count_classref_len += classrefsize;
+               count_parsed_desc_len += descsize;
+       }
+#endif
+
+       /* parse the loaded descriptors */
+       for (i=0; i<c->cpcount; ++i) {
+               constant_FMIref *fmi;
+               
+               switch (c->cptags[i]) {
+                       case CONSTANT_Class:
+                               /* XXX set classref */
+                               break;
+                       case CONSTANT_Fieldref:
+                               fmi = (constant_FMIref *)c->cpinfos[i];
+                               fmi->parseddesc.fd = 
+                                       descriptor_pool_parse_field_descriptor(descpool,fmi->descriptor);
+                               if (!fmi->parseddesc.fd)
+                                       goto return_exception;
+                               fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
+                               break;
+                       case CONSTANT_Methodref:
+                       case CONSTANT_InterfaceMethodref:
+                               fmi = (constant_FMIref *)c->cpinfos[i];
+                               fmi->parseddesc.md = 
+                                       descriptor_pool_parse_method_descriptor(descpool,fmi->descriptor);
+                               if (!fmi->parseddesc.md)
+                                       goto return_exception;
+                               fmi->classref = descriptor_pool_lookup_classref(descpool,fmi->class->name);
+                               break;
+               }
+       }
+       for (i = 0; i < c->fieldscount; i++) {
+               c->fields[i].parseddesc = descriptor_pool_parse_field_descriptor(descpool,c->fields[i].descriptor);
+               if (!c->fields[i].parseddesc)
+                       goto return_exception;
+       }
+       for (i = 0; i < c->methodscount; i++) {
+               c->methods[i].parseddesc = descriptor_pool_parse_method_descriptor(descpool,c->methods[i].descriptor);
+               if (!c->methods[i].parseddesc)
+                       goto return_exception;
        }
 
        /* Check if all fields and methods can be uniquely
@@ -2386,7 +2432,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                                        new_classformaterror(c,
                                                                                                 "Repetitive field name/signature");
 
-                                               return NULL;
+                                               goto return_exception;
                                        }
                                } while ((old = next[old]));
                        }
@@ -2420,7 +2466,7 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                                                        new_classformaterror(c,
                                                                                                 "Repetitive method name/signature");
 
-                                               return NULL;
+                                               goto return_exception;
                                        }
                                } while ((old = next[old]));
                        }
@@ -2440,10 +2486,10 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
        /* load attribute structures */
        if (!check_classbuffer_size(cb, 2))
-               return NULL;
+               goto return_exception;
 
        if (!load_attributes(cb, suck_u2(cb)))
-               return NULL;
+               goto return_exception;
 
 #if 0
        /* Pre java 1.5 version don't check this. This implementation is like
@@ -2457,15 +2503,25 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
                if (classdata_left > 0) {
                        *exceptionptr =
                                new_classformaterror(c, "Extra bytes at the end of class file");
-                       return NULL;
+                       goto return_exception;
                }
        }
 #endif
 
+       /* release dump area */
+       dump_release(dumpsize);
+       
        if (loadverbose)
                log_message_class("Loading done class: ", c);
 
        return c;
+
+return_exception:
+       /* release dump area */
+       dump_release(dumpsize);
+
+       /* an exception has been thrown */
+       return NULL;
 }
 
 
@@ -2480,6 +2536,8 @@ void class_new_array(classinfo *c)
 {
        classinfo *comp = NULL;
        methodinfo *clone;
+       methoddesc *clonedesc;
+       constant_classref *classrefs;
        int namelen;
 
        /* Check array class name */
@@ -2547,11 +2605,22 @@ void class_new_array(classinfo *c)
        c->methodscount = 1;
        c->methods = MNEW(methodinfo, c->methodscount);
 
+       classrefs = MNEW(constant_classref,1);
+       CLASSREF_INIT(classrefs[0],c,utf_java_lang_Object);
+
+       clonedesc = NEW(methoddesc);
+       clonedesc->returntype.type = TYPE_ADDRESS;
+       clonedesc->returntype.classref = classrefs;
+       clonedesc->returntype.arraydim = 0;
+       clonedesc->paramcount = 0;
+       clonedesc->paramslots = 0;
+
        clone = c->methods;
        MSET(clone, 0, methodinfo, 1);
        clone->flags = ACC_PUBLIC;
        clone->name = utf_new_char("clone");
        clone->descriptor = utf_void__java_lang_Object;
+       clone->parseddesc = clonedesc;
        clone->class = c;
        clone->stubroutine = createnativestub((functionptr) &builtin_clone_array, clone);
        clone->monoPoly = MONO;
@@ -2560,6 +2629,12 @@ void class_new_array(classinfo *c)
 
        /* array classes are not loaded from class files */
        c->loaded = true;
+       c->parseddescs = (u1*) clonedesc;
+       c->parseddescsize = sizeof(methodinfo);
+       c->classrefs = classrefs;
+       c->classrefcount = 1;
+
+       /* XXX insert class into the loaded class cache */
 }
 
 
index 52dd1f53f847dee4b634c5cb78d7fee81d66866e..569c8255e71a4e88c9468348b442254b62a92b8f 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Reinhard Grafl
 
-   $Id: loader.h 2154 2005-03-30 20:03:06Z twisti $
+   $Id: loader.h 2181 2005-04-01 16:53:33Z edwin $
 */
 
 
@@ -42,13 +42,11 @@ typedef struct classbuffer classbuffer;
 typedef struct classpath_info classpath_info;
 
 
-#include "config.h"
-#include "types.h"
-#include "vm/class.h"
-#include "vm/descriptor.h"
 #include "vm/global.h"
-#include "vm/method.h"
 #include "vm/utf8.h"
+#include "vm/references.h"
+#include "vm/descriptor.h"
+#include "vm/method.h"
 
 #if defined(USE_ZLIB)
 # include "vm/unzip.h"
@@ -86,15 +84,6 @@ typedef struct classpath_info classpath_info;
 
 *******************************************************************************/
 
-typedef struct {            /* Fieldref, Methodref and InterfaceMethodref     */
-       classinfo *class;       /* class containing this field/method/intfmeth.   */ /* XXX remove */
-       constant_classref *classref;  /* class containing this field/meth./intfm. */
-       utf       *name;        /* field/method/interfacemethod name              */
-       utf       *descriptor;  /* field/method/intfmeth. type descriptor string  */
-       parseddesc parseddesc;  /* parsed descriptor                              */
-} constant_FMIref;
-
-
 typedef struct {            /* Integer                                        */
        s4 value;
 } constant_integer;
@@ -213,7 +202,6 @@ classinfo *class_init(classinfo *c);
 /* debug purposes */
 void class_showmethods(classinfo *c);
 void class_showconstantpool(classinfo *c);
-void print_arraydescriptor(FILE *file, arraydescriptor *desc);
 
 /* return the primitive class inidicated by the given signature character */
 classinfo *class_primitive_from_sig(char sig);
index 1012c6870a27461fa410d87d96188b5548dea6fa..7012c6873393f3fd56c2cd0b5eaac7f9b4865da9 100644 (file)
             Edwin Steiner
             Christian Thalinger
 
-   $Id: method.c 2100 2005-03-28 21:57:23Z twisti $
+   $Id: method.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
 
+#include "vm/global.h"
 #include "mm/memory.h"
 #include "vm/method.h"
+#include "vm/class.h"
 #include "vm/jit/codegen.inc.h"
 
 
index 06553ea9d26dce8c6981449d2465f4a8e16a3902..eb653f320874221dcb1e3fc4a4b77e9c1260739b 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Christian Thalinger
 
-   $Id: method.h 2114 2005-03-29 21:42:33Z twisti $
+   $Id: method.h 2181 2005-04-01 16:53:33Z edwin $
 */
 
 
@@ -42,10 +42,10 @@ typedef struct exceptiontable exceptiontable;
 typedef struct lineinfo lineinfo; 
 
 
-#include "vm/class.h"
-#include "vm/descriptor.h"
 #include "vm/global.h"
 #include "vm/utf8.h"
+#include "vm/references.h"
+#include "vm/descriptor.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/inline/parseXTA.h"
 
diff --git a/src/vm/references.h b/src/vm/references.h
new file mode 100644 (file)
index 0000000..0810af4
--- /dev/null
@@ -0,0 +1,135 @@
+/* vm/references.h - references to classes/fields/methods
+
+   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
+
+   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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.
+
+   Contact: cacao@complang.tuwien.ac.at
+
+   Authors: Edwin Steiner
+
+   Changes:
+
+   $Id: references.h 2181 2005-04-01 16:53:33Z edwin $
+
+*/
+
+#ifndef _REFERENCES_H_
+#define _REFERENCES_H_
+
+#include "vm/global.h"
+#include "vm/utf8.h"
+
+/*----------------------------------------------------------------------------*/
+/* References                                                                 */
+/*                                                                            */
+/* This header files defines the following types used for references to       */
+/* classes/methods/fields and descriptors:                                    */
+/*                                                                            */
+/*     classinfo *                a loaded class                              */
+/*     constant_classref          a symbolic reference                        */
+/*     classref_or_classinfo      a loaded class or a symbolic reference      */
+/*                                                                            */
+/*     constant_FMIref            a symb. ref. to a field/method/intf.method  */
+/*                                                                            */
+/*     typedesc *                 describes a field type                      */
+/*     methoddesc *               descrives a method type                     */
+/*     parseddesc                 describes a field type or a method type     */
+/*----------------------------------------------------------------------------*/
+
+/* forward declarations *******************************************************/
+
+typedef struct classinfo classinfo; 
+typedef struct typedesc typedesc;
+typedef struct methoddesc methoddesc;
+
+/* structs ********************************************************************/
+
+/* constant_classref **********************************************************/
+
+typedef struct constant_classref {
+       void      *pseudo_vftbl;      /* for distinguishing it from classinfo     */
+       classinfo *referer;           /* class containing the reference           */
+       utf       *name;              /* name of the class refered to             */
+} constant_classref;
+
+/* classref_or_classinfo ******************************************************/
+
+typedef union {
+       constant_classref *ref;       /* a symbolic class reference               */
+       classinfo         *cls;       /* an already loaded class                  */
+       void              *any;       /* used for general access (x != NULL,...)  */
+} classref_or_classinfo;
+
+/* parseddesc *****************************************************************/
+
+typedef union parseddesc {
+       typedesc          *fd;        /* parsed field descriptor                  */
+       methoddesc        *md;        /* parsed method descriptor                 */
+       void              *any;       /* used for simple test against NULL        */
+} parseddesc;
+
+/* constant_FMIref ************************************************************/
+
+typedef struct {            /* Fieldref, Methodref and InterfaceMethodref     */
+       classinfo *class;       /* class containing this field/method/intfmeth.   */ /* XXX remove */
+       constant_classref *classref;  /* class containing this field/meth./intfm. */
+       utf       *name;        /* field/method/interfacemethod name              */
+       utf       *descriptor;  /* field/method/intfmeth. type descriptor string  */
+       parseddesc parseddesc;  /* parsed descriptor                              */
+} constant_FMIref;
+
+/* macros *********************************************************************/
+
+/* a value that never occurrs in classinfo.header.vftbl                       */
+#define CLASSREF_PSEUDO_VFTBL ((void *) 1)
+
+/* macro for testing if a classref_or_classinfo is a classref                 */
+/* `reforinfo` is only evaluated once                                         */
+#define IS_CLASSREF(reforinfo)  \
+       ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL)
+
+/* macro for casting a classref/classinfo * to a classref_or_classinfo        */
+#define CLASSREF_OR_CLASSINFO(value) \
+       (*((classref_or_classinfo *)(&(value))))
+
+/* initialize a constant_classref with referer `ref` and name `classname`     */
+#define CLASSREF_INIT(c,ref,classname)                          \
+                       do { (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL;      \
+                                (c).referer = (ref);                           \
+                                (c).name = (classname); } while (0)
+
+#endif /* _REFERENCES_H_ */
+
+/*
+ * 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 3d59f36e7f6c08b0d90423ce0b26b67bd26737c0..79a1affa353a7df2308355b86dc3ae3853cff2ba 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: resolve.c 2148 2005-03-30 16:49:40Z twisti $
+   $Id: resolve.c 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -48,6 +48,8 @@
 /* DEBUG HELPERS                                                              */
 /******************************************************************************/
 
+/*#define RESOLVE_VERBOSE*/
+
 #ifndef NDEBUG
 #define RESOLVE_DEBUG
 #endif
@@ -70,6 +72,8 @@ resolve_class(classinfo *referer,methodinfo *refmethod,
                          classinfo **result)
 {
        classinfo *cls = NULL;
+       char *utf_ptr;
+       int len;
        
        RESOLVE_ASSERT(result);
        RESOLVE_ASSERT(referer);
@@ -78,7 +82,7 @@ resolve_class(classinfo *referer,methodinfo *refmethod,
        
        *result = NULL;
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"resolve_class(");
        utf_fprint(stderr,referer->name);
        fprintf(stderr,",");
@@ -89,35 +93,62 @@ resolve_class(classinfo *referer,methodinfo *refmethod,
        /* lookup if this class has already been loaded */
        cls = classcache_lookup(referer->classloader,classname);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    lookup result: %p\n",(void*)cls);
 #endif
        
        if (!cls) {
-               /* the class has not been loaded, yet */
-               if (mode == resolveLazy)
-                       return true; /* be lazy */
+               /* 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(referer,refmethod,
+                                                                          utf_new(utf_ptr,len),
+                                                                          mode,&cls))
+                                               return false; /* exception */
+                                       if (!cls) {
+                                               RESOLVE_ASSERT(mode == resolveLazy);
+                                               return true; /* be lazy */
+                                       }
+                                       /* create the array class */
+                                       cls = class_array_of(cls);
+                       }
+               }
+               else {
+                       /* the class has not been loaded, yet */
+                       if (mode == resolveLazy)
+                               return true; /* be lazy */
+               }
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
                fprintf(stderr,"    loading...\n");
 #endif
 
                /* load the class */
-#ifdef XXX
-               if (!load_class(referer->classloader,classname,&cls))
-                       return false; /* exception */
-#else
-               cls = class_new(classname);
-               if (!cls->loaded)
-                       load_class_from_classloader(cls, referer->classloader);
-#endif
+               if (!cls) {
+                       classinfo *c = class_new(classname);
+                       cls = load_class_from_classloader(c,referer->classloader);
+                       if (!cls) {
+                               class_free(c);
+                               return false; /* exception */
+                       }
+               }
        }
 
        /* the class is now loaded */
        RESOLVE_ASSERT(cls);
        RESOLVE_ASSERT(cls->loaded);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    checking access rights...\n");
 #endif
        
@@ -129,7 +160,7 @@ resolve_class(classinfo *referer,methodinfo *refmethod,
        }
 
        /* resolution succeeds */
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    success.\n");
 #endif
        *result = cls;
@@ -174,7 +205,7 @@ resolve_classref_or_classinfo(methodinfo *refmethod,
 
        if (link) {
                if (!c->linked)
-                       if (!class_link(c))
+                       if (!link_class(c))
                                return false; /* exception */
                RESOLVE_ASSERT(c->linked);
        }
@@ -210,7 +241,7 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
        RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
        RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"resolve_and_check_subtype_set\n");
        unresolved_subtype_set_debug_dump(ref,stderr);
        if (IS_CLASSREF(typeref)) {
@@ -256,7 +287,7 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
                RESOLVE_ASSERT(result->loaded);
                RESOLVE_ASSERT(result->linked);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
                fprintf(stderr,"performing subclass test:\n");
                fprintf(stderr,"    ");utf_fprint(stderr,result->name);fputc('\n',stderr);
                fprintf(stderr,"  must be a %s of\n",(reversed) ? "superclass" : "subclass");
@@ -266,16 +297,18 @@ resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
                /* now check the subtype relationship */
                TYPEINFO_INIT_CLASSINFO(resultti,result);
                if (reversed) {
-                       if (!typeinfo_is_assignable_to_classinfo(&typeti,result)) {
-#ifdef RESOLVE_DEBUG
+                       /* we must test against `true` because `MAYBE` is also != 0 */
+                       if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
+#ifdef RESOLVE_VERBOSE
                                fprintf(stderr,"reversed subclass test failed\n");
 #endif
                                goto throw_error;
                        }
                }
                else {
-                       if (!typeinfo_is_assignable_to_classinfo(&resultti,type)) {
-#ifdef RESOLVE_DEBUG
+                       /* we must test against `true` because `MAYBE` is also != 0 */
+                       if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
+#ifdef RESOLVE_VERBOSE
                                fprintf(stderr,"subclass test failed\n");
 #endif
                                goto throw_error;
@@ -321,7 +354,7 @@ resolve_field(unresolved_field *ref,
 
        *result = NULL;
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        unresolved_field_debug_dump(ref,stderr);
 #endif
 
@@ -345,7 +378,7 @@ resolve_field(unresolved_field *ref,
        /* now we must find the declaration of the field in `container`
         * or one of its superclasses */
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
                fprintf(stderr,"    resolving field in class...\n");
 #endif
 
@@ -360,7 +393,7 @@ resolve_field(unresolved_field *ref,
        RESOLVE_ASSERT(declarer);
        RESOLVE_ASSERT(declarer->loaded && declarer->linked);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
                fprintf(stderr,"    checking static...\n");
 #endif
 
@@ -375,7 +408,7 @@ resolve_field(unresolved_field *ref,
 
        /* for non-static accesses we have to check the constraints on the instance type */
        if ((ref->flags & RESOLVE_STATIC) == 0) {
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
                fprintf(stderr,"    checking instance types...\n");
 #endif
 
@@ -396,6 +429,7 @@ resolve_field(unresolved_field *ref,
 
        /* for PUT* instructions we have to check the constraints on the value type */
        if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
+               RESOLVE_ASSERT(fieldtyperef);
                if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
                        /* check subtype constraints */
                        if (!resolve_and_check_subtype_set(referer,ref->referermethod,
@@ -436,6 +470,7 @@ resolve_field(unresolved_field *ref,
 
        /* impose loading constraint on field type */
        if (fi->type == TYPE_ADR) {
+               RESOLVE_ASSERT(fieldtyperef);
                if (!classcache_add_constraint(declarer->classloader,referer->classloader,
                                                                           fieldtyperef->name))
                        return false; /* exception */
@@ -469,7 +504,7 @@ resolve_method(unresolved_method *ref,
        RESOLVE_ASSERT(result);
        RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        unresolved_method_debug_dump(ref,stderr);
 #endif
 
@@ -628,7 +663,7 @@ unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
        RESOLVE_ASSERT(stset);
        RESOLVE_ASSERT(tinfo);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
 #ifdef TYPEINFO_DEBUG
        typeinfo_print(stderr,tinfo,4);
@@ -665,17 +700,20 @@ unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
                count = tinfo->merged->count;
                stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
                for (i=0; i<count; ++i) {
-                       stset->subtyperefs[i].cls = tinfo->merged->list[i];
+                       stset->subtyperefs[i] = tinfo->merged->list[i];
                }
                stset->subtyperefs[count].any = NULL; /* terminate */
        }
        else {
-               if (tinfo->typeclass->name == declaredtype->name) {
+               if ((IS_CLASSREF(tinfo->typeclass)
+                                       ? tinfo->typeclass.ref->name 
+                                       : tinfo->typeclass.cls->name) == declaredtype->name)
+               {
                        goto empty_set;
                }
                else {
                        stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
-                       stset->subtyperefs[0].cls = tinfo->typeclass;
+                       stset->subtyperefs[0] = tinfo->typeclass;
                        stset->subtyperefs[1].any = NULL; /* terminate */
                }
        }
@@ -700,7 +738,7 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod,
        typeinfo *tip = NULL;
        typedesc *fd;
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"create_unresolved_field\n");
        fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
        fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
@@ -752,7 +790,7 @@ create_unresolved_field(classinfo *referer,methodinfo *refmethod,
        fd = fieldref->parseddesc.fd;
        RESOLVE_ASSERT(fd);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
        fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
        fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
@@ -831,7 +869,7 @@ create_unresolved_method(classinfo *referer,methodinfo *refmethod,
        md = methodref->parseddesc.md;
        RESOLVE_ASSERT(md);
 
-#ifdef RESOLVE_DEBUG
+#ifdef RESOLVE_VERBOSE
        fprintf(stderr,"create_unresolved_method\n");
        fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
        fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
index b3b20faa9d153c63fd3a66b8ae58c29c574dbe14..3145d28e5dc9542f6063a4e19028a79dd2416462 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: resolve.h 2112 2005-03-29 21:29:08Z twisti $
+   $Id: resolve.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -44,7 +44,7 @@ typedef struct unresolved_subtype_set unresolved_subtype_set;
 
 
 #include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/references.h"
 #include "vm/jit/jit.h"
 
 
@@ -68,15 +68,6 @@ typedef enum {
 } resolve_err_t;
 
 
-/* classref_or_classinfo ******************************************************/
-
-typedef union {
-       constant_classref *ref;       /* a symbolic class reference               */
-       classinfo         *cls;       /* an already loaded class                  */
-       void              *any;       /* used for general access (x != NULL,...)  */
-} classref_or_classinfo;
-
-
 /* structs ********************************************************************/
 
 struct unresolved_subtype_set {
@@ -110,19 +101,6 @@ struct unresolved_method {
 #define UNRESOLVED_SUBTYPE_SET_EMTPY(stset) \
        do { (stset).subtyperefs = NULL; } while(0)
 
-/* a value that never occurrs in classinfo.header.vftbl                       */
-#define CLASSREF_PSEUDO_VFTBL ((vftbl_t *) 1)
-
-/* macro for testing if a classref_or_classinfo is a classref                 */
-/* `reforinfo` is only evaluated once                                         */
-#define IS_CLASSREF(reforinfo)  \
-       ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL)
-
-/* macro for casting a classref/classinfo * to a classref_or_classinfo        */
-#define CLASSREF_OR_CLASSINFO(value) \
-       (*((classref_or_classinfo *)(&(value))))
-
-
 /* function prototypes ********************************************************/
 
 /* resolve_class ***************************************************************
index 099861060d71ff33ae2d15a8dff6cd9148e09e00..30a09dcbe238a08904a71e3a34545b44d7ffef47 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: stringlocal.h 1926 2005-02-10 10:47:29Z twisti $
+   $Id: stringlocal.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -41,8 +41,8 @@ typedef struct literalstring literalstring;
 
 #include "native/include/java_lang_String.h"
 #include "vm/global.h"
-#include "vm/tables.h"
 #include "vm/utf8.h"
+#include "vm/tables.h"
 
 
 /* data structure of internal javastrings stored in global hashtable **********/
index d5b648a56c23f0b90c5a28a2411807894ebd96df..991314fcc2434aa960883474368be6c550e96821 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: utf8.h 2158 2005-03-30 20:06:37Z twisti $
+   $Id: utf8.h 2181 2005-04-01 16:53:33Z edwin $
 
 */
 
@@ -44,7 +44,6 @@
 typedef struct utf utf;
 
 
-#include "types.h"
 #include "vm/global.h"