Merge from subtype.
[cacao.git] / src / vm / descriptor.c
index 419a1a552d29dbe82774fb715849c07c72ed627d..235154e42170a6b62fd37f6e93da951fc8115d1a 100644 (file)
@@ -1,9 +1,7 @@
 /* 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.
-
-   Contact: cacao@complang.tuwien.ac.at
-
-   Authors: Edwin Steiner
-
-   Changes: Christian Thalinger
-            Christian Ullrich
-
-   $Id: descriptor.c 3826 2005-12-01 18:52:50Z edwin $
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
 */
 
 
+#include "config.h"
+
 #include <assert.h>
 
-#include "types.h"
+#include "vm/types.h"
+
 #include "md-abi.h"
 
 #include "mm/memory.h"
+
 #include "vm/descriptor.h"
-#include "vm/exceptions.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.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) ****************************************/
@@ -56,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;
@@ -72,7 +68,7 @@ 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 */
 };
 
@@ -145,29 +141,43 @@ struct descriptor_hash_entry {
 
 *******************************************************************************/
 
-u2 descriptor_to_basic_type(utf *descriptor)
+int descriptor_to_basic_type(utf *descriptor)
 {
        assert(descriptor->blength >= 1);
        
        switch (descriptor->text[0]) {
-               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 'L':
-               case '[':  return TYPE_ADDRESS;
+       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]);
        }
-                       
-       assert(0);
 
-       return 0; /* keep the compiler happy */
+       /* keep the compiler happy */
+
+       return 0;
 }
 
-/* descriptor_typesize**** ****************************************************
+
+/* descriptor_typesize *********************************************************
 
    Return the size in bytes needed for the given type.
 
@@ -179,23 +189,32 @@ u2 descriptor_to_basic_type(utf *descriptor)
 
 *******************************************************************************/
 
-u2 descriptor_typesize(typedesc *td)
+int descriptor_typesize(typedesc *td)
 {
        assert(td);
 
        switch (td->type) {
-               case TYPE_INT:     return 4;
-               case TYPE_LONG:    return 8;
-               case TYPE_FLOAT:   return 4;
-               case TYPE_DOUBLE:  return 8;
-               case TYPE_ADDRESS: return sizeof(voidptr);
+       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);
        }
 
-       assert(0);
+       /* keep the compiler happy */
 
-       return 0; /* keep the compiler happy */
+       return 0;
 }
 
+
 /* name_from_descriptor ********************************************************
 
    Return the class name indicated by the given descriptor
@@ -283,7 +302,7 @@ name_from_descriptor(classinfo *c,
                }
        }
 
-       *exceptionptr = new_classformaterror(c,"invalid descriptor");
+       exceptions_throw_classformaterror(c, "Invalid descriptor");
        return false;
 }
 
@@ -319,8 +338,8 @@ descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
 
        if (name) {
                /* a reference type */
-               td->type = TYPE_ADDRESS;
-               td->decltype = TYPE_ADDRESS;
+               td->type = TYPE_ADR;
+               td->primitivetype = TYPE_ADR;
                td->arraydim = 0;
                for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
                        td->arraydim++;
@@ -330,39 +349,39 @@ descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
                /* a primitive type */
                switch (*utf_ptr) {
                case 'B': 
-                       td->decltype = PRIMITIVETYPE_BYTE;
+                       td->primitivetype = PRIMITIVETYPE_BYTE;
                        td->type = TYPE_INT;
                        break;
                case 'C':
-                       td->decltype = PRIMITIVETYPE_CHAR;
+                       td->primitivetype = PRIMITIVETYPE_CHAR;
                        td->type = TYPE_INT;
                        break;
                case 'S':  
-                       td->decltype = PRIMITIVETYPE_SHORT;
+                       td->primitivetype = PRIMITIVETYPE_SHORT;
                        td->type = TYPE_INT;
                        break;
                case 'Z':
-                       td->decltype = PRIMITIVETYPE_BOOLEAN;
+                       td->primitivetype = PRIMITIVETYPE_BOOLEAN;
                        td->type = TYPE_INT;
                        break;
                case 'I':
-                       td->decltype = PRIMITIVETYPE_INT;
+                       td->primitivetype = PRIMITIVETYPE_INT;
                        td->type = TYPE_INT;
                        break;
                case 'D':
-                       td->decltype = PRIMITIVETYPE_DOUBLE;
-                       td->type = TYPE_DOUBLE;
+                       td->primitivetype = PRIMITIVETYPE_DOUBLE;
+                       td->type = TYPE_DBL;
                        break;
                case 'F':
-                       td->decltype = PRIMITIVETYPE_FLOAT;
-                       td->type = TYPE_FLOAT;
+                       td->primitivetype = PRIMITIVETYPE_FLOAT;
+                       td->type = TYPE_FLT;
                        break;
                case 'J':
-                       td->decltype = PRIMITIVETYPE_LONG;
-                       td->type = TYPE_LONG;
+                       td->primitivetype = PRIMITIVETYPE_LONG;
+                       td->type = TYPE_LNG;
                        break;
                case 'V':
-                       td->decltype = PRIMITIVETYPE_VOID;
+                       td->primitivetype = PRIMITIVETYPE_VOID;
                        td->type = TYPE_VOID;
                        break;
                default:
@@ -413,14 +432,14 @@ 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;
 
@@ -453,7 +472,7 @@ descriptor_pool_add_class(descriptor_pool *pool, utf *name)
 
 #ifdef DESCRIPTOR_VERBOSE
        fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
-       utf_fprint(stderr,name);fprintf(stderr,")\n");
+       utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
 #endif
 
        /* find a place in the hashtable */
@@ -471,8 +490,7 @@ 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");
+               exceptions_throw_classformaterror(pool->referer, "Invalid class name");
                return false; /* exception */
        }
 
@@ -518,7 +536,7 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
        
 #ifdef DESCRIPTOR_VERBOSE
        fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
-       utf_fprint(stderr,desc);fprintf(stderr,")\n");
+       utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
 #endif
 
        assert(pool);
@@ -587,7 +605,8 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
                }
 
                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;
                }
 
@@ -602,8 +621,8 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
                                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;
                }
 
@@ -712,7 +731,7 @@ descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
                c = c->hashlink;
        }
 
-       *exceptionptr = new_internalerror("Class reference not found in descriptor pool");
+       exceptions_throw_internalerror("Class reference not found in descriptor pool");
        return NULL;
 }
 
@@ -808,8 +827,8 @@ descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
        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;
        }
 
@@ -865,7 +884,7 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
 #ifdef DESCRIPTOR_VERBOSE
        fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
                        (void*)pool,(int)mflags,(void*)thisclass);
-       utf_fprint(stderr,desc); fprintf(stderr,")\n");
+       utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
 #endif
 
        assert(pool);
@@ -875,8 +894,8 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
        /* check that it is a method descriptor */
        
        if (desc->text[0] != '(') {
-               *exceptionptr = new_classformaterror(pool->referer,
-                               "Field descriptor used in method reference");
+               exceptions_throw_classformaterror(pool->referer,
+                                                                                 "Field descriptor used in method reference");
                return NULL;
        }
 
@@ -909,7 +928,7 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
 
        if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
                td->type = TYPE_ADR;
-               td->decltype = TYPE_ADR;
+               td->primitivetype = TYPE_ADR;
                td->arraydim = 0;
                td->classref = thisclass;
 
@@ -925,7 +944,7 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
                if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
                        return NULL;
 
-               if (td->type == TYPE_LONG || td->type == TYPE_DOUBLE)
+               if (IS_2_WORD_TYPE(td->type))
                        paramslots++;
                
                td++;
@@ -955,8 +974,8 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
        md->paramcount = paramcount;
        md->paramslots = paramslots;
 
-       /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
-       /* Otherwise we do this in stack analysis.                                */
+       /* 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) {
@@ -969,13 +988,29 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
                }
 
                /* 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...  */
-               md_param_alloc(md);
+               /* 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                                                        */
+               /* params will be allocated later by
+                  descriptor_params_from_paramtypes if necessary */
+
                md->params = NULL;
        }
 
@@ -1035,7 +1070,7 @@ bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
                /* fill in first argument `this' */
 
                td->type = TYPE_ADR;
-               td->decltype = TYPE_ADR;
+               td->primitivetype = TYPE_ADR;
                td->arraydim = 0;
                td->classref = thisclass;
 
@@ -1049,16 +1084,30 @@ bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
                /* allocate memory for params */
 
                md->params = MNEW(paramdesc, md->paramcount);
-       }
-       else {
+
+       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.. */
-
-       md_param_alloc(md);
+       /* 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;
 }
@@ -1155,14 +1204,14 @@ descriptor_debug_print_typedesc(FILE *file,typedesc *d)
                return;
        }
        
-       if (d->type == TYPE_ADDRESS) {
+       if (d->type == TYPE_ADR) {
                if (d->classref)
-                       utf_fprint(file,d->classref->name);
+                       utf_fprint_printable_ascii(file,d->classref->name);
                else
                        fprintf(file,"<class=NULL>");
        }
        else {
-               switch (d->decltype) {
+               switch (d->primitivetype) {
                        case PRIMITIVETYPE_INT    : ch='I'; break;
                        case PRIMITIVETYPE_CHAR   : ch='C'; break;
                        case PRIMITIVETYPE_BYTE   : ch='B'; break;
@@ -1260,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);
@@ -1276,7 +1325,7 @@ descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
                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;
                }
@@ -1287,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;
                }
@@ -1321,10 +1370,10 @@ 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*);
                        }
                }
        }