Merge from subtype.
[cacao.git] / src / vm / descriptor.c
index fdc5bc9aa06c9683148dca01527b013a6b788a11..235154e42170a6b62fd37f6e93da951fc8115d1a 100644 (file)
@@ -1,9 +1,7 @@
-/* vm/descriptor.c - checking and parsing of field / method descriptors
+/* src/vm/descriptor.c - checking and parsing of field / method descriptors
 
-   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
-   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
-   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
-   Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+*/
 
-   Authors: Edwin Steiner
 
-   Changes:
+#include "config.h"
 
-   $Id: descriptor.c 2111 2005-03-29 21:28:24Z twisti $
+#include <assert.h>
 
-*/
+#include "vm/types.h"
 
-#include <assert.h>
+#include "md-abi.h"
+
+#include "mm/memory.h"
 
 #include "vm/descriptor.h"
-#include "vm/exceptions.h"
-#include "vm/resolve.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/abi.h"
 
 
 /* constants (private to descriptor.c) ****************************************/
@@ -49,7 +52,7 @@
 /* (currently the hash is never grown!) */
 #define DESCRIPTORHASH_INIT_SIZE  128
 
-/* data structures (private to descriptor.c) **********************************/ 
+/* data structures (private to descriptor.c) **********************************/
 
 typedef struct classref_hash_entry classref_hash_entry;
 typedef struct descriptor_hash_entry descriptor_hash_entry;
@@ -65,22 +68,152 @@ struct classref_hash_entry {
 struct descriptor_hash_entry {
        descriptor_hash_entry *hashlink;
        utf                   *desc;
-       parseddesc             parseddesc;
+       parseddesc_t           parseddesc;
+       s2                     paramslots; /* number of params, LONG/DOUBLE counted as 2 */
 };
 
+
+/****************************************************************************/
+/* MACROS FOR DESCRIPTOR PARSING (private 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)
+
+
 /****************************************************************************/
 /* DEBUG HELPERS                                                            */
 /****************************************************************************/
 
-#ifndef NDEBUG
-#define DESCRIPTOR_DEBUG
-#endif
+/*#define DESCRIPTOR_VERBOSE*/
+
+/****************************************************************************/
+/* FUNCTIONS                                                                */
+/****************************************************************************/
+
+/* descriptor_to_basic_type ****************************************************
+
+   Return the basic type to use for a value with this descriptor.
+
+   IN:
+       utf..............descriptor utf string
+
+   OUT:
+       A TYPE_* constant.
+
+   PRECONDITIONS:
+       This function assumes that the descriptor has passed 
+          descriptor_pool_add checks and that it does not start with '('.
+
+*******************************************************************************/
+
+int descriptor_to_basic_type(utf *descriptor)
+{
+       assert(descriptor->blength >= 1);
+       
+       switch (descriptor->text[0]) {
+       case 'Z':
+       case 'B':
+       case 'C':
+       case 'S':
+       case 'I':
+               return TYPE_INT;
+
+       case 'J':
+               return TYPE_LNG;
+
+       case 'F':
+               return TYPE_FLT;
+
+       case 'D':
+               return TYPE_DBL;
+
+       case 'L':
+       case '[':
+               return TYPE_ADR;
+
+       default:
+               vm_abort("descriptor_to_basic_type: invalid type %c",
+                                descriptor->text[0]);
+       }
+
+       /* keep the compiler happy */
+
+       return 0;
+}
+
+
+/* descriptor_typesize *********************************************************
+
+   Return the size in bytes needed for the given type.
+
+   IN:
+       td..............typedesc describing the type
+
+   OUT:
+       The number of bytes
+
+*******************************************************************************/
+
+int descriptor_typesize(typedesc *td)
+{
+       assert(td);
+
+       switch (td->type) {
+       case TYPE_INT:
+       case TYPE_FLT:
+               return 4;
+
+       case TYPE_LNG:
+       case TYPE_DBL:
+               return 8;
+
+       case TYPE_ADR:
+               return SIZEOF_VOID_P;
+
+       default:
+               vm_abort("descriptor_typesize: invalid type %d", td->type);
+       }
+
+       /* keep the compiler happy */
+
+       return 0;
+}
 
-#ifdef DESCRIPTOR_DEBUG
-#define DESCRIPTOR_ASSERT(cond)  assert(cond)
-#else
-#define DESCRIPTOR_ASSERT(cond)
-#endif
 
 /* name_from_descriptor ********************************************************
 
@@ -130,10 +263,10 @@ name_from_descriptor(classinfo *c,
        char *start = utf_ptr;
        bool error = false;
 
-       DESCRIPTOR_ASSERT(c);
-       DESCRIPTOR_ASSERT(utf_ptr);
-       DESCRIPTOR_ASSERT(end_ptr);
-       DESCRIPTOR_ASSERT(name);
+       assert(c);
+       assert(utf_ptr);
+       assert(end_ptr);
+       assert(name);
        
        *name = NULL;           
        SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
@@ -169,49 +302,11 @@ name_from_descriptor(classinfo *c,
                }
        }
 
-       *exceptionptr = new_classformaterror(c,"invalid descriptor");
+       exceptions_throw_classformaterror(c, "Invalid descriptor");
        return false;
 }
 
-/* primitive_type_from_char ****************************************************
-   Return the primitive type corresponding to the given descriptor character
-   (Internally used helper function)
-
-   IN:
-       ch...............the character
 
-   RETURN VALUE:
-       The primitive type (a TYPE_* constant)
-
-   NOTE:
-       This function assumes that the descriptor has already been checked.
-
-*******************************************************************************/
-
-static int
-primitive_type_from_char(int ch)
-{
-       switch (ch) {
-               case 'B': 
-               case 'C':
-               case 'I':
-               case 'S':  
-               case 'Z':
-                       return TYPE_INT;
-               case 'D':
-                       return TYPE_DOUBLE;
-               case 'F':
-                       return TYPE_FLOAT;
-               case 'J':
-                       return TYPE_LONG;
-               case 'V':
-                       return TYPE_VOID;
-       }
-       DESCRIPTOR_ASSERT(false);
-       return 0; /* for the compiler */
-}
-                               
 /* descriptor_to_typedesc ******************************************************
  
    Parse the given type descriptor and fill a typedesc struct
@@ -233,33 +328,74 @@ primitive_type_from_char(int ch)
 *******************************************************************************/
 
 static bool
-descriptor_to_typedesc(descriptor_pool *pool,char *utf_ptr,char *end_pos,
-                                          char **next,typedesc *d)
+descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
+                                          char **next, typedesc *td)
 {
        utf *name;
        
-       if (!name_from_descriptor(pool->referer,utf_ptr,end_pos,next,0,&name))
+       if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
                return false;
 
        if (name) {
                /* a reference type */
-               d->type = TYPE_ADDRESS;
-               d->arraydim = 0;
-               for (utf_ptr=name->text; *utf_ptr == '['; ++utf_ptr)
-                       d->arraydim++;
-               d->classref = descriptor_pool_lookup_classref(pool,name);
-       }
-       else {
-               DESCRIPTOR_ASSERT(utf_ptr[0] != '[' && utf_ptr[0] != 'L');
+               td->type = TYPE_ADR;
+               td->primitivetype = TYPE_ADR;
+               td->arraydim = 0;
+               for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
+                       td->arraydim++;
+               td->classref = descriptor_pool_lookup_classref(pool, name);
+
+       } else {
                /* a primitive type */
-               d->type = primitive_type_from_char(*utf_ptr);
-               d->arraydim = 0;
-               d->classref = NULL;
+               switch (*utf_ptr) {
+               case 'B': 
+                       td->primitivetype = PRIMITIVETYPE_BYTE;
+                       td->type = TYPE_INT;
+                       break;
+               case 'C':
+                       td->primitivetype = PRIMITIVETYPE_CHAR;
+                       td->type = TYPE_INT;
+                       break;
+               case 'S':  
+                       td->primitivetype = PRIMITIVETYPE_SHORT;
+                       td->type = TYPE_INT;
+                       break;
+               case 'Z':
+                       td->primitivetype = PRIMITIVETYPE_BOOLEAN;
+                       td->type = TYPE_INT;
+                       break;
+               case 'I':
+                       td->primitivetype = PRIMITIVETYPE_INT;
+                       td->type = TYPE_INT;
+                       break;
+               case 'D':
+                       td->primitivetype = PRIMITIVETYPE_DOUBLE;
+                       td->type = TYPE_DBL;
+                       break;
+               case 'F':
+                       td->primitivetype = PRIMITIVETYPE_FLOAT;
+                       td->type = TYPE_FLT;
+                       break;
+               case 'J':
+                       td->primitivetype = PRIMITIVETYPE_LONG;
+                       td->type = TYPE_LNG;
+                       break;
+               case 'V':
+                       td->primitivetype = PRIMITIVETYPE_VOID;
+                       td->type = TYPE_VOID;
+                       break;
+               default:
+                       assert(false);
+               }
+
+               td->arraydim = 0;
+               td->classref = NULL;
        }
 
        return true;
 }
 
+
 /* descriptor_pool_new *********************************************************
  
    Allocate a new descriptor_pool
@@ -280,7 +416,7 @@ descriptor_pool_new(classinfo *referer)
        u4 slot;
 
        pool = DNEW(descriptor_pool);
-       DESCRIPTOR_ASSERT(pool);
+       assert(pool);
 
        pool->referer = referer;
        pool->fieldcount = 0;
@@ -296,20 +432,21 @@ descriptor_pool_new(classinfo *referer)
        hashsize = CLASSREFHASH_INIT_SIZE;
        pool->classrefhash.size = hashsize;
        pool->classrefhash.entries = 0;
-       pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
+       pool->classrefhash.ptr = DMNEW(void*, hashsize);
        for (slot=0; slot<hashsize; ++slot)
                pool->classrefhash.ptr[slot] = NULL;
 
        hashsize = DESCRIPTORHASH_INIT_SIZE;
        pool->descriptorhash.size = hashsize;
        pool->descriptorhash.entries = 0;
-       pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
+       pool->descriptorhash.ptr = DMNEW(void*, hashsize);
        for (slot=0; slot<hashsize; ++slot)
                pool->descriptorhash.ptr[slot] = NULL;
 
        return pool;
 }
 
+
 /* descriptor_pool_add_class ***************************************************
  
    Add the given class reference to the pool
@@ -325,18 +462,25 @@ descriptor_pool_new(classinfo *referer)
 *******************************************************************************/
 
 bool 
-descriptor_pool_add_class(descriptor_pool *pool,utf *name)
+descriptor_pool_add_class(descriptor_pool *pool, utf *name)
 {
        u4 key,slot;
        classref_hash_entry *c;
        
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT(name);
+       assert(pool);
+       assert(name);
+
+#ifdef DESCRIPTOR_VERBOSE
+       fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
+       utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
+#endif
 
        /* find a place in the hashtable */
+
        key = utf_hashkey(name->text, name->blength);
        slot = key & (pool->classrefhash.size - 1);
        c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
        while (c) {
                if (c->name == name)
                        return true; /* already stored */
@@ -344,10 +488,13 @@ descriptor_pool_add_class(descriptor_pool *pool,utf *name)
        }
 
        /* check if the name is a valid classname */
-       if (!is_valid_name(name->text,utf_end(name))) {
-               *exceptionptr = new_classformaterror(pool->referer,"Invalid class name");
+
+       if (!is_valid_name(name->text,UTF_END(name))) {
+               exceptions_throw_classformaterror(pool->referer, "Invalid class name");
                return false; /* exception */
        }
+
+       /* XXX check maximum array dimension */
        
        c = DNEW(classref_hash_entry);
        c->name = name;
@@ -358,6 +505,7 @@ descriptor_pool_add_class(descriptor_pool *pool,utf *name)
        return true;
 }
 
+
 /* descriptor_pool_add *********************************************************
  
    Check the given descriptor and add it to the pool
@@ -366,6 +514,10 @@ descriptor_pool_add_class(descriptor_pool *pool,utf *name)
        pool.............the descriptor_pool
           desc.............the descriptor to add. Maybe a field or method desc.
 
+   OUT:
+       *paramslots......if non-NULL, set to the number of parameters.
+                           LONG and DOUBLE are counted twice
+
    RETURN VALUE:
        true.............descriptor has been added
           false............an exception has been thrown
@@ -373,97 +525,131 @@ descriptor_pool_add_class(descriptor_pool *pool,utf *name)
 *******************************************************************************/
 
 bool 
-descriptor_pool_add(descriptor_pool *pool,utf *desc)
+descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
 {
        u4 key,slot;
-       descriptor_hash_entry *c;
+       descriptor_hash_entry *d;
        char *utf_ptr;
        char *end_pos;
        utf *name;
+       s4 argcount = 0;
        
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT(desc);
+#ifdef DESCRIPTOR_VERBOSE
+       fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
+       utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
+#endif
+
+       assert(pool);
+       assert(desc);
 
        /* find a place in the hashtable */
+
        key = utf_hashkey(desc->text, desc->blength);
        slot = key & (pool->descriptorhash.size - 1);
-       c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-       while (c) {
-               if (c->desc == desc)
-                       return true; /* already stored */
-               c = c->hashlink;
+       d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+       /* Save all method descriptors in the hashtable, since the parsed         */
+       /* descriptor may vary between differenf methods (static vs. non-static). */
+
+       utf_ptr = desc->text;
+
+       if (*utf_ptr != '(') {
+               while (d) {
+                       if (d->desc == desc) {
+                               if (paramslots)
+                                       *paramslots = d->paramslots;
+                               return true; /* already stored */
+                       }
+                       d = d->hashlink;
+               }
        }
+
        /* add the descriptor to the pool */
-       c = DNEW(descriptor_hash_entry);
-       c->desc = desc;
-       c->parseddesc.any = NULL;
-       c->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-       pool->descriptorhash.ptr[slot] = c;
+
+       d = DNEW(descriptor_hash_entry);
+       d->desc = desc;
+       d->parseddesc.any = NULL;
+       d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+       pool->descriptorhash.ptr[slot] = d;
 
        /* now check the descriptor */
-       utf_ptr = desc->text;
-       end_pos = utf_end(desc);
+
+       end_pos = UTF_END(desc);
        
        if (*utf_ptr == '(') {
-               s4 argcount = 0;
-               
                /* a method descriptor */
+
                pool->methodcount++;
                utf_ptr++;
 
                /* check arguments */
-               while (utf_ptr != end_pos && *utf_ptr != ')') {
+
+               while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
                        pool->paramcount++;
-                       /* We cannot count the this argument here because
+
+                       /* We cannot count the `this' argument here because
                         * we don't know if the method is static. */
+
                        if (*utf_ptr == 'J' || *utf_ptr == 'D')
-                               argcount+=2;
+                               argcount += 2;
                        else
                                argcount++;
-                       if (!name_from_descriptor(pool->referer,utf_ptr,end_pos,&utf_ptr,
-                                                                     DESCRIPTOR_NOVOID,&name))
+
+                       if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
+                                                                     DESCRIPTOR_NOVOID, &name))
                                return false;
 
                        if (name)
-                               descriptor_pool_add_class(pool,name);
+                               if (!descriptor_pool_add_class(pool, name))
+                                       return false;
                }
 
                if (utf_ptr == end_pos) {
-                       *exceptionptr = new_classformaterror(pool->referer,"Missing ')' in method descriptor");
+                       exceptions_throw_classformaterror(pool->referer,
+                                                                                         "Missing ')' in method descriptor");
                        return false;
                }
 
                utf_ptr++; /* skip ')' */
 
-               if (!name_from_descriptor(pool->referer,utf_ptr,end_pos,NULL,
-                                                                 DESCRIPTOR_CHECKEND,&name))
+               if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+                                                                 DESCRIPTOR_CHECKEND, &name))
                        return false;
 
                if (name)
-                       descriptor_pool_add_class(pool,name);
+                       if (!descriptor_pool_add_class(pool,name))
+                               return false;
 
                if (argcount > 255) {
-                       *exceptionptr =
-                               new_classformaterror(pool->referer,"Too many arguments in signature");
+                       exceptions_throw_classformaterror(pool->referer,
+                                                                                         "Too many arguments in signature");
                        return false;
                }
-       }
-       else {
+
+       else {
                /* a field descriptor */
+
                pool->fieldcount++;
                
-           if (!name_from_descriptor(pool->referer,utf_ptr,end_pos,NULL,
-                                                         DESCRIPTOR_NOVOID
-                                                               | DESCRIPTOR_CHECKEND,&name))
+           if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+                                                         DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
+                                                                 &name))
                        return false;
 
                if (name)
-                       descriptor_pool_add_class(pool,name);
+                       if (!descriptor_pool_add_class(pool,name))
+                               return false;
        }
 
+       d->paramslots = argcount;
+
+       if (paramslots)
+               *paramslots = argcount;
+
        return true;
 }
 
+
 /* descriptor_pool_create_classrefs ********************************************
  
    Create a table containing all the classrefs which were added to the pool
@@ -481,33 +667,36 @@ descriptor_pool_add(descriptor_pool *pool,utf *desc)
 *******************************************************************************/
 
 constant_classref * 
-descriptor_pool_create_classrefs(descriptor_pool *pool,s4 *count)
+descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
 {
        u4 nclasses;
        u4 slot;
        classref_hash_entry *c;
        constant_classref *ref;
        
-       DESCRIPTOR_ASSERT(pool);
+       assert(pool);
 
        nclasses = pool->classrefhash.entries;
        pool->classrefs = MNEW(constant_classref,nclasses);
 
        /* fill the constant_classref structs */
-       for (slot=0; slot<pool->classrefhash.size; ++slot) {
+
+       for (slot = 0; slot < pool->classrefhash.size; ++slot) {
                c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
                while (c) {
                        ref = pool->classrefs + c->index;
-                       CLASSREF_INIT(*ref,pool->referer,c->name);
+                       CLASSREF_INIT(*ref, pool->referer, c->name);
                        c = c->hashlink;
                }
        }
 
        if (count)
                *count = nclasses;
+
        return pool->classrefs;
 }
 
+
 /* descriptor_pool_lookup_classref *********************************************
  
    Return the constant_classref for the given class name
@@ -523,29 +712,30 @@ descriptor_pool_create_classrefs(descriptor_pool *pool,s4 *count)
 *******************************************************************************/
 
 constant_classref * 
-descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname)
+descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
 {
        u4 key,slot;
        classref_hash_entry *c;
 
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT(pool->classrefs);
-       DESCRIPTOR_ASSERT(classname);
+       assert(pool);
+       assert(pool->classrefs);
+       assert(classname);
 
        key = utf_hashkey(classname->text, classname->blength);
        slot = key & (pool->classrefhash.size - 1);
        c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
        while (c) {
                if (c->name == classname)
                        return pool->classrefs + c->index;
                c = c->hashlink;
        }
 
-       *exceptionptr = new_exception_message(string_java_lang_InternalError,
-                                                                                 "Class reference not found in descriptor pool");
+       exceptions_throw_internalerror("Class reference not found in descriptor pool");
        return NULL;
 }
 
+
 /* descriptor_pool_alloc_parsed_descriptors ************************************
  
    Allocate space for the parsed descriptors
@@ -564,25 +754,31 @@ descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
 {
        u4 size;
        
-       DESCRIPTOR_ASSERT(pool);
+       assert(pool);
+
+       /* TWISTI: paramcount + 1: we don't know if the method is static or   */
+       /* not, i have no better solution yet.                                */
 
-       size = pool->fieldcount * sizeof(typedesc)
-                + pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc))
-                + pool->paramcount * sizeof(typedesc);
+       size =
+               pool->fieldcount * sizeof(typedesc) +
+               pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
+               pool->paramcount * sizeof(typedesc) +
+               pool->methodcount * sizeof(typedesc);      /* possible `this' pointer */
 
        pool->descriptorsize = size;
        if (size) {
-               pool->descriptors = MNEW(u1,size);
+               pool->descriptors = MNEW(u1, size);
                pool->descriptors_next = pool->descriptors;
        }
 
        size = pool->fieldcount + pool->methodcount;
        if (size) {
-               pool->descriptor_kind = DMNEW(u1,size);
+               pool->descriptor_kind = DMNEW(u1, size);
                pool->descriptor_kind_next = pool->descriptor_kind;
        }
 }
 
+
 /* descriptor_pool_parse_field_descriptor **************************************
  
    Parse the given field descriptor
@@ -596,145 +792,327 @@ descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
           NULL if an exception has been thrown
 
    NOTE:
-       descriptor_pool_alloc_parsed_descriptors must be called (once) before this
-          function is used.
+       descriptor_pool_alloc_parsed_descriptors must be called (once)
+       before this function is used.
 
 *******************************************************************************/
 
 typedesc * 
-descriptor_pool_parse_field_descriptor(descriptor_pool *pool,utf *desc)
+descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
 {
        u4 key,slot;
-       descriptor_hash_entry *c;
-       typedesc *d;
+       descriptor_hash_entry *d;
+       typedesc *td;
 
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT(pool->descriptors);
-       DESCRIPTOR_ASSERT(pool->descriptors_next);
+       assert(pool);
+       assert(pool->descriptors);
+       assert(pool->descriptors_next);
 
        /* lookup the descriptor in the hashtable */
+
        key = utf_hashkey(desc->text, desc->blength);
        slot = key & (pool->descriptorhash.size - 1);
-       c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-       while (c) {
-               if (c->desc == desc) {
+       d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+       while (d) {
+               if (d->desc == desc) {
                        /* found */
-                       if (c->parseddesc.fd)
-                               return c->parseddesc.fd;
+                       if (d->parseddesc.fd)
+                               return d->parseddesc.fd;
                        break;
                }
-               c = c->hashlink;
+               d = d->hashlink;
        }
 
-       DESCRIPTOR_ASSERT(c);
+       assert(d);
        
        if (desc->text[0] == '(') {
-               *exceptionptr = new_classformaterror(pool->referer,
-                               "Method descriptor used in field reference");
+               exceptions_throw_classformaterror(pool->referer,
+                                                                                 "Method descriptor used in field reference");
                return NULL;
        }
 
-       d = (typedesc *) pool->descriptors_next;
+       td = (typedesc *) pool->descriptors_next;
        pool->descriptors_next += sizeof(typedesc);
        
-       if (!descriptor_to_typedesc(pool,desc->text,utf_end(desc),NULL,d))
+       if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
                return NULL;
 
        *(pool->descriptor_kind_next++) = 'f';
 
-       c->parseddesc.fd = d;
-       return d;
+       d->parseddesc.fd = td;
+
+       return td;
 }
 
+
 /* descriptor_pool_parse_method_descriptor *************************************
  
    Parse the given method descriptor
 
    IN:
        pool.............the descriptor_pool
-          desc.............the method descriptor
+       desc.............the method descriptor
+       mflags...........the method flags
+          thisclass........classref to the class containing the method.
+                                               This is ignored if mflags contains ACC_STATIC.
+                                               The classref is stored for inserting the 'this' argument.
 
    RETURN VALUE:
        a pointer to the parsed method descriptor, or
           NULL if an exception has been thrown
 
-   NOTE:
-       descriptor_pool_alloc_parsed_descriptors must be called (once) before this
-          function is used.
+   NOTE: 
+       descriptor_pool_alloc_parsed_descriptors must be called
+       (once) before this function is used.
 
 *******************************************************************************/
 
 methoddesc * 
-descriptor_pool_parse_method_descriptor(descriptor_pool *pool,utf *desc)
+descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
+                                                                               s4 mflags,constant_classref *thisclass)
 {
-       u4 key,slot;
-       descriptor_hash_entry *c;
-       typedesc *d;
-       methoddesc *md;
+       u4 key, slot;
+       descriptor_hash_entry *d;
+       methoddesc            *md;
+       typedesc              *td;
        char *utf_ptr;
        char *end_pos;
        s2 paramcount = 0;
        s2 paramslots = 0;
 
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT(pool->descriptors);
-       DESCRIPTOR_ASSERT(pool->descriptors_next);
+#ifdef DESCRIPTOR_VERBOSE
+       fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
+                       (void*)pool,(int)mflags,(void*)thisclass);
+       utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
+#endif
+
+       assert(pool);
+       assert(pool->descriptors);
+       assert(pool->descriptors_next);
+
+       /* check that it is a method descriptor */
+       
+       if (desc->text[0] != '(') {
+               exceptions_throw_classformaterror(pool->referer,
+                                                                                 "Field descriptor used in method reference");
+               return NULL;
+       }
 
        /* lookup the descriptor in the hashtable */
+
        key = utf_hashkey(desc->text, desc->blength);
        slot = key & (pool->descriptorhash.size - 1);
-       c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-       while (c) {
-               if (c->desc == desc) {
-                       /* found */
-                       if (c->parseddesc.md)
-                               return c->parseddesc.md;
-                       break;
-               }
-               c = c->hashlink;
+       d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+       /* find an un-parsed descriptor */
+
+       while (d) {
+               if (d->desc == desc)
+                       if (!d->parseddesc.md)
+                               break;
+               d = d->hashlink;
        }
 
-       DESCRIPTOR_ASSERT(c);
-       
+       assert(d);
+
        md = (methoddesc *) pool->descriptors_next;
        pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
 
-       utf_ptr = desc->text;
-       end_pos = utf_end(desc);
+       utf_ptr = desc->text + 1; /* skip '(' */
+       end_pos = UTF_END(desc);
 
-       if (*utf_ptr++ != '(') {
-               *exceptionptr = new_classformaterror(pool->referer,
-                               "Field descriptor used in method reference");
-               return NULL;
+       td = md->paramtypes;
+
+       /* count the `this' pointer */
+
+       if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
+               td->type = TYPE_ADR;
+               td->primitivetype = TYPE_ADR;
+               td->arraydim = 0;
+               td->classref = thisclass;
+
+               td++;
+               pool->descriptors_next += sizeof(typedesc);
+               paramcount++;
+               paramslots++;
        }
 
-       d = md->paramtypes;
        while (*utf_ptr != ')') {
                /* parse a parameter type */
-               if (!descriptor_to_typedesc(pool,utf_ptr,end_pos,&utf_ptr,d))
+
+               if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
                        return NULL;
 
-               if (d->type == TYPE_LONG || d->type == TYPE_DOUBLE)
+               if (IS_2_WORD_TYPE(td->type))
                        paramslots++;
                
-               d++;
+               td++;
                pool->descriptors_next += sizeof(typedesc);
                paramcount++;
                paramslots++;
        }
        utf_ptr++; /* skip ')' */
-       
+
+       /* Skip possible `this' pointer in paramtypes array to allow a possible   */
+       /* memory move later in parse.                                            */
+       /* We store the thisclass reference, so we can later correctly fill in    */
+       /* the parameter slot of the 'this' argument.                             */
+
+       if (mflags == ACC_UNDEF) {
+               td->classref = thisclass;
+               td++;
+               pool->descriptors_next += sizeof(typedesc);
+       }
+
        /* parse return type */
-       if (!descriptor_to_typedesc(pool,utf_ptr,end_pos,NULL,&(md->returntype)))
-                       return NULL;
+
+       if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
+                                                               &(md->returntype)))
+               return NULL;
 
        md->paramcount = paramcount;
        md->paramslots = paramslots;
+
+       /* If mflags != ACC_UNDEF we parse a real loaded method, so do
+          param prealloc.  Otherwise we do this in stack analysis. */
+
+       if (mflags != ACC_UNDEF) {
+               if (md->paramcount > 0) {
+                       /* allocate memory for params */
+
+                       md->params = MNEW(paramdesc, md->paramcount);
+               }
+               else {
+                       md->params = METHODDESC_NOPARAMS;
+               }
+
+               /* fill the paramdesc */
+               /* md_param_alloc has to be called if md->paramcount == 0,
+                  too, so it can make the reservation for the Linkage Area,
+                  Return Register... */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+               if (!opt_intrp)
+# endif
+                       {
+                               /* As builtin-functions are native functions, we have
+                                  to pre-allocate for the native ABI. */
+
+                               if (mflags & ACC_METHOD_BUILTIN)
+                                       md_param_alloc_native(md);
+                               else
+                                       md_param_alloc(md);
+                       }
+#endif
+       }
+       else {
+               /* params will be allocated later by
+                  descriptor_params_from_paramtypes if necessary */
+
+               md->params = NULL;
+       }
+
        *(pool->descriptor_kind_next++) = 'm';
-       c->parseddesc.md = md;
+
+       d->parseddesc.md = md;
+
        return md;
 }
 
+/* descriptor_params_from_paramtypes *******************************************
+   Create the paramdescs for a method descriptor. This function is called
+   when we know whether the method is static or not. This function may only
+   be called once for each methoddesc, and only if md->params == NULL.
+
+   IN:
+       md...............the parsed method descriptor
+                           md->params MUST be NULL.
+          mflags...........the ACC_* access flags of the method. Only the
+                           ACC_STATIC bit is checked.
+                                               The value ACC_UNDEF is NOT allowed.
+
+   RETURN VALUE:
+       true.............the paramdescs were created successfully
+          false............an exception has been thrown
+
+   POSTCONDITION:
+       md->parms != NULL
+
+*******************************************************************************/
+
+bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
+{
+       typedesc *td;
+
+       assert(md);
+       assert(md->params == NULL);
+       assert(mflags != ACC_UNDEF);
+
+       td = md->paramtypes;
+
+       /* check for `this' pointer */
+
+       if (!(mflags & ACC_STATIC)) {
+               constant_classref *thisclass;
+
+               /* fetch class reference from reserved param slot */
+               thisclass = td[md->paramcount].classref;
+               assert(thisclass);
+
+               if (md->paramcount > 0) {
+                       /* shift param types by 1 argument */
+                       MMOVE(td + 1, td, typedesc, md->paramcount);
+               }
+
+               /* fill in first argument `this' */
+
+               td->type = TYPE_ADR;
+               td->primitivetype = TYPE_ADR;
+               td->arraydim = 0;
+               td->classref = thisclass;
+
+               md->paramcount++;
+               md->paramslots++;
+       }
+
+       /* if the method has params, process them */
+
+       if (md->paramcount > 0) {
+               /* allocate memory for params */
+
+               md->params = MNEW(paramdesc, md->paramcount);
+
+       } else {
+               md->params = METHODDESC_NOPARAMS;
+       }
+
+       /* fill the paramdesc */
+       /* md_param_alloc has to be called if md->paramcount == 0, too, so
+          it can make the reservation for the Linkage Area, Return
+          Register.. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+       if (!opt_intrp)
+# endif
+               {
+                       /* As builtin-functions are native functions, we have to
+                          pre-allocate for the native ABI. */
+
+                       if (mflags & ACC_METHOD_BUILTIN)
+                               md_param_alloc_native(md);
+                       else
+                               md_param_alloc(md);
+               }
+#endif
+
+       return true;
+}
+
+
 /* descriptor_pool_get_parsed_descriptors **************************************
  
    Return a pointer to the block of parsed descriptors
@@ -750,22 +1128,24 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool,utf *desc)
        a pointer to the block of parsed descriptors
 
    NOTE:
-       descriptor_pool_alloc_parsed_descriptors must be called (once) before this
-          function is used.
+       descriptor_pool_alloc_parsed_descriptors must be called (once)
+       before this function is used.
 
 *******************************************************************************/
 
 void * 
-descriptor_pool_get_parsed_descriptors(descriptor_pool *pool,s4 *size)
+descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
 {
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+       assert(pool);
+       assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
        
        if (size)
                *size = pool->descriptorsize;
+
        return pool->descriptors;
 }
 
+
 /* descriptor_pool_get_sizes ***************************************************
  
    Get the sizes of the class reference table and the parsed descriptors
@@ -786,19 +1166,24 @@ descriptor_pool_get_parsed_descriptors(descriptor_pool *pool,s4 *size)
 *******************************************************************************/
 
 void 
-descriptor_pool_get_sizes(descriptor_pool *pool,
-                                             u4 *classrefsize,u4 *descsize)
+descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
 {
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
-       DESCRIPTOR_ASSERT(pool->classrefs);
-       DESCRIPTOR_ASSERT(classrefsize);
-       DESCRIPTOR_ASSERT(descsize);
+       assert(pool);
+       assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+       assert(pool->classrefs);
+       assert(classrefsize);
+       assert(descsize);
 
        *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
        *descsize = pool->descriptorsize;
 }
 
+
+/****************************************************************************/
+/* DEBUG HELPERS                                                            */
+/****************************************************************************/
+
+#ifndef NDEBUG
 /* descriptor_debug_print_typedesc *********************************************
  
    Print the given typedesc to the given stream
@@ -819,18 +1204,24 @@ descriptor_debug_print_typedesc(FILE *file,typedesc *d)
                return;
        }
        
-       if (d->type == TYPE_ADDRESS) {
-               utf_fprint(file,d->classref->name);
+       if (d->type == TYPE_ADR) {
+               if (d->classref)
+                       utf_fprint_printable_ascii(file,d->classref->name);
+               else
+                       fprintf(file,"<class=NULL>");
        }
        else {
-               switch (d->type) {
-                       case TYPE_INT    : ch='I'; break;
-                       case TYPE_LONG   : ch='J'; break;
-                       case TYPE_FLOAT  : ch='F'; break;
-                       case TYPE_DOUBLE : ch='D'; break;
-                       case TYPE_ADDRESS: ch='A'; break;
-                       case TYPE_VOID   : ch='V'; break;
-                       default          : ch='!';
+               switch (d->primitivetype) {
+                       case PRIMITIVETYPE_INT    : ch='I'; break;
+                       case PRIMITIVETYPE_CHAR   : ch='C'; break;
+                       case PRIMITIVETYPE_BYTE   : ch='B'; break;
+                       case PRIMITIVETYPE_SHORT  : ch='S'; break;
+                       case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
+                       case PRIMITIVETYPE_LONG   : ch='J'; break;
+                       case PRIMITIVETYPE_FLOAT  : ch='F'; break;
+                       case PRIMITIVETYPE_DOUBLE : ch='D'; break;
+                       case PRIMITIVETYPE_VOID   : ch='V'; break;
+                       default                   : ch='!';
                }
                fputc(ch,file);
        }
@@ -838,6 +1229,32 @@ descriptor_debug_print_typedesc(FILE *file,typedesc *d)
                fprintf(file,"[%d]",d->arraydim);
 }
 
+/* descriptor_debug_print_paramdesc ********************************************
+   Print the given paramdesc to the given stream
+
+   IN:
+          file.............stream to print to
+          d................the parameter descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
+{
+       if (!d) {
+               fprintf(file,"(paramdesc *)NULL");
+               return;
+       }
+       
+       if (d->inmemory) {
+               fprintf(file,"<m%d>",d->regoff);
+       }
+       else {
+               fprintf(file,"<r%d>",d->regoff);
+       }
+}
+
 /* descriptor_debug_print_methoddesc *******************************************
  
    Print the given methoddesc to the given stream
@@ -863,7 +1280,12 @@ descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
                if (i)
                        fputc(',',file);
                descriptor_debug_print_typedesc(file,d->paramtypes + i);
+               if (d->params) {
+                       descriptor_debug_print_paramdesc(file,d->params + i);
+               }
        }
+       if (d->params == METHODDESC_NOPARAMS)
+               fputs("<NOPARAMS>",file);
        fputc(')',file);
        descriptor_debug_print_typedesc(file,&(d->returntype));
 }
@@ -887,7 +1309,7 @@ descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
        u4 size;
        
        fprintf(file,"======[descriptor_pool for ");
-       utf_fprint(file,pool->referer->name);
+       utf_fprint_printable_ascii(file,pool->referer->name);
        fprintf(file,"]======\n");
 
        fprintf(file,"fieldcount:     %d\n",pool->fieldcount);
@@ -896,14 +1318,14 @@ descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
        fprintf(file,"classrefcount:  %d\n",pool->classrefhash.entries);
        fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
        fprintf(file,"classrefsize:   %d bytes\n",
-                       pool->classrefhash.entries * sizeof(constant_classref));
+                       (int)(pool->classrefhash.entries * sizeof(constant_classref)));
 
        fprintf(file,"class references:\n");
        for (slot=0; slot<pool->classrefhash.size; ++slot) {
                classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
                while (c) {
                        fprintf(file,"    %4d: ",c->index);
-                       utf_fprint(file,c->name);
+                       utf_fprint_printable_ascii(file,c->name);
                        fprintf(file,"\n");
                        c = c->hashlink;
                }
@@ -914,7 +1336,7 @@ descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
                descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
                while (c) {
                        fprintf(file,"    %p: ",c->parseddesc.any);
-                       utf_fprint(file,c->desc);
+                       utf_fprint_printable_ascii(file,c->desc);
                        fprintf(file,"\n");
                        c = c->hashlink;
                }
@@ -948,16 +1370,17 @@ descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
                        }
                }
                else {
-                       while (size >= sizeof(voidptr)) {
-                               fprintf(file,"    %p\n",*((voidptr*)pos));
-                               pos += sizeof(voidptr);
-                               size -= sizeof(voidptr);
+                       while (size >= sizeof(void*)) {
+                               fprintf(file,"    %p\n",*((void**)pos));
+                               pos += sizeof(void*);
+                               size -= sizeof(void*);
                        }
                }
        }
 
        fprintf(file,"==========================================================\n");
 }
+#endif /* !defined(NDEBUG) */
 
 /*
  * These are local overrides for various environment variables in Emacs.