* src/vm/jit/alpha/codegen.c (codegen): Use lock_monitor_enter/exit
[cacao.git] / src / vm / descriptor.c
index a54c4c04cf5861a11578702ccf5cb09b0e61e78e..8b30632895f360a6dd76e96d4f72bf1095c5ad73 100644 (file)
@@ -1,9 +1,9 @@
 /* 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 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Edwin Steiner
 
    Changes: Christian Thalinger
             Christian Ullrich
 
-   $Id: descriptor.c 2833 2005-06-26 21:47:29Z christian $
+   $Id: descriptor.c 4879 2006-05-05 17:34:49Z edwin $
 
 */
 
 
+#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/options.h"
 #include "vm/resolve.h"
 #include "vm/stringlocal.h"
 
@@ -123,15 +127,78 @@ struct descriptor_hash_entry {
 /* DEBUG HELPERS                                                            */
 /****************************************************************************/
 
-#ifndef NDEBUG
-#define DESCRIPTOR_DEBUG
-#endif
+/*#define DESCRIPTOR_VERBOSE*/
 
-#ifdef DESCRIPTOR_DEBUG
-#define DESCRIPTOR_ASSERT(cond)  assert(cond)
-#else
-#define DESCRIPTOR_ASSERT(cond)
-#endif
+/****************************************************************************/
+/* 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 '('.
+
+*******************************************************************************/
+
+u2 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;
+       }
+                       
+       assert(0);
+
+       return 0; /* keep the compiler happy */
+}
+
+/* descriptor_typesize**** ****************************************************
+
+   Return the size in bytes needed for the given type.
+
+   IN:
+       td..............typedesc describing the type
+
+   OUT:
+       The number of bytes
+
+*******************************************************************************/
+
+u2 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);
+       }
+
+       assert(0);
+
+       return 0; /* keep the compiler happy */
+}
 
 /* name_from_descriptor ********************************************************
 
@@ -181,10 +248,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);
@@ -303,7 +370,7 @@ descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
                        td->type = TYPE_VOID;
                        break;
                default:
-                       DESCRIPTOR_ASSERT(false);
+                       assert(false);
                }
 
                td->arraydim = 0;
@@ -334,7 +401,7 @@ descriptor_pool_new(classinfo *referer)
        u4 slot;
 
        pool = DNEW(descriptor_pool);
-       DESCRIPTOR_ASSERT(pool);
+       assert(pool);
 
        pool->referer = referer;
        pool->fieldcount = 0;
@@ -385,8 +452,13 @@ 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 */
 
@@ -448,8 +520,13 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
        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 */
 
@@ -509,7 +586,8 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
                                return false;
 
                        if (name)
-                               descriptor_pool_add_class(pool, name);
+                               if (!descriptor_pool_add_class(pool, name))
+                                       return false;
                }
 
                if (utf_ptr == end_pos) {
@@ -524,7 +602,8 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
                        return false;
 
                if (name)
-                       descriptor_pool_add_class(pool,name);
+                       if (!descriptor_pool_add_class(pool,name))
+                               return false;
 
                if (argcount > 255) {
                        *exceptionptr =
@@ -534,6 +613,7 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
 
        } else {
                /* a field descriptor */
+
                pool->fieldcount++;
                
            if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
@@ -542,7 +622,8 @@ descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
                        return false;
 
                if (name)
-                       descriptor_pool_add_class(pool,name);
+                       if (!descriptor_pool_add_class(pool,name))
+                               return false;
        }
 
        d->paramslots = argcount;
@@ -578,7 +659,7 @@ descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
        classref_hash_entry *c;
        constant_classref *ref;
        
-       DESCRIPTOR_ASSERT(pool);
+       assert(pool);
 
        nclasses = pool->classrefhash.entries;
        pool->classrefs = MNEW(constant_classref,nclasses);
@@ -621,9 +702,9 @@ 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);
@@ -635,9 +716,7 @@ descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
                c = c->hashlink;
        }
 
-       *exceptionptr =
-               new_exception_message(string_java_lang_InternalError,
-                                                         "Class reference not found in descriptor pool");
+       *exceptionptr = new_internalerror("Class reference not found in descriptor pool");
        return NULL;
 }
 
@@ -660,7 +739,7 @@ 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.                                */
@@ -710,9 +789,9 @@ descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
        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 */
 
@@ -730,7 +809,7 @@ descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
                d = d->hashlink;
        }
 
-       DESCRIPTOR_ASSERT(d);
+       assert(d);
        
        if (desc->text[0] == '(') {
                *exceptionptr = new_classformaterror(pool->referer,
@@ -787,9 +866,23 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
        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] != '(') {
+               *exceptionptr = new_classformaterror(pool->referer,
+                               "Field descriptor used in method reference");
+               return NULL;
+       }
 
        /* lookup the descriptor in the hashtable */
 
@@ -806,20 +899,14 @@ descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
                d = d->hashlink;
        }
 
-       DESCRIPTOR_ASSERT(d);
+       assert(d);
 
        md = (methoddesc *) pool->descriptors_next;
        pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
 
-       utf_ptr = desc->text;
+       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 */
@@ -886,13 +973,21 @@ 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);
-       }
-       else {
-               /* params will be allocated later by descriptor_params_from_paramtypes */
-               /* if necessary                                                        */
+               /* 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
+                       md_param_alloc(md);
+#endif
+
+       } else {
+               /* params will be allocated later by
+                  descriptor_params_from_paramtypes if necessary */
+
                md->params = NULL;
        }
 
@@ -929,9 +1024,9 @@ bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
 {
        typedesc *td;
 
-       DESCRIPTOR_ASSERT(md);
-       DESCRIPTOR_ASSERT(md->params == NULL);
-       DESCRIPTOR_ASSERT(mflags != ACC_UNDEF);
+       assert(md);
+       assert(md->params == NULL);
+       assert(mflags != ACC_UNDEF);
 
        td = md->paramtypes;
 
@@ -942,7 +1037,7 @@ bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
 
                /* fetch class reference from reserved param slot */
                thisclass = td[md->paramcount].classref;
-               DESCRIPTOR_ASSERT(thisclass);
+               assert(thisclass);
 
                if (md->paramcount > 0) {
                        /* shift param types by 1 argument */
@@ -966,16 +1061,22 @@ 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
+               md_param_alloc(md);
+#endif
 
        return true;
 }
@@ -1004,8 +1105,8 @@ bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
 void * 
 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;
@@ -1036,17 +1137,22 @@ descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
 void 
 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
@@ -1069,7 +1175,7 @@ descriptor_debug_print_typedesc(FILE *file,typedesc *d)
        
        if (d->type == TYPE_ADDRESS) {
                if (d->classref)
-                       utf_fprint(file,d->classref->name);
+                       utf_fprint_printable_ascii(file,d->classref->name);
                else
                        fprintf(file,"<class=NULL>");
        }
@@ -1172,7 +1278,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);
@@ -1188,7 +1294,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;
                }
@@ -1199,7 +1305,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;
                }
@@ -1243,6 +1349,7 @@ descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
 
        fprintf(file,"==========================================================\n");
 }
+#endif /* !defined(NDEBUG) */
 
 /*
  * These are local overrides for various environment variables in Emacs.