Initial import of s390 codegen, codebase is copyed from x86_64.
[cacao.git] / src / vm / descriptor.c
index fa34c60aced72d5c4c4f8d6836cb72ac32f6f9d2..c5e512d89be3f7416138abda31f41852fb86fb1f 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, 2007 R. Grafl, A. Krall, C. Kruegel,
+   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+   J. Wenninger, Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Edwin Steiner
-
-   Changes: Christian Thalinger
+            Christian Thalinger
             Christian Ullrich
 
-   $Id: descriptor.c 3380 2005-10-06 13:48:16Z edwin $
+   $Id: descriptor.c 6286 2007-01-10 10:03:38Z twisti $
 
 */
 
 
+#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"
 
@@ -125,15 +128,76 @@ struct descriptor_hash_entry {
 
 /*#define DESCRIPTOR_VERBOSE*/
 
-#ifndef NDEBUG
-#define DESCRIPTOR_DEBUG
-#endif
+/****************************************************************************/
+/* FUNCTIONS                                                                */
+/****************************************************************************/
 
-#ifdef DESCRIPTOR_DEBUG
-#define DESCRIPTOR_ASSERT(cond)  assert(cond)
-#else
-#define DESCRIPTOR_ASSERT(cond)
-#endif
+/* 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_DBL;
+               case 'F':  return TYPE_FLT;
+               case 'J':  return TYPE_LNG;
+               case 'L':
+               case '[':  return TYPE_ADR;
+       }
+                       
+       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_LNG: return 8;
+               case TYPE_FLT: return 4;
+               case TYPE_DBL: return 8;
+               case TYPE_ADR: return sizeof(voidptr);
+       }
+
+       assert(0);
+
+       return 0; /* keep the compiler happy */
+}
 
 /* name_from_descriptor ********************************************************
 
@@ -183,10 +247,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);
@@ -258,8 +322,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->decltype = TYPE_ADR;
                td->arraydim = 0;
                for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
                        td->arraydim++;
@@ -290,22 +354,22 @@ descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
                        break;
                case 'D':
                        td->decltype = PRIMITIVETYPE_DOUBLE;
-                       td->type = TYPE_DOUBLE;
+                       td->type = TYPE_DBL;
                        break;
                case 'F':
                        td->decltype = PRIMITIVETYPE_FLOAT;
-                       td->type = TYPE_FLOAT;
+                       td->type = TYPE_FLT;
                        break;
                case 'J':
                        td->decltype = PRIMITIVETYPE_LONG;
-                       td->type = TYPE_LONG;
+                       td->type = TYPE_LNG;
                        break;
                case 'V':
                        td->decltype = PRIMITIVETYPE_VOID;
                        td->type = TYPE_VOID;
                        break;
                default:
-                       DESCRIPTOR_ASSERT(false);
+                       assert(false);
                }
 
                td->arraydim = 0;
@@ -336,7 +400,7 @@ descriptor_pool_new(classinfo *referer)
        u4 slot;
 
        pool = DNEW(descriptor_pool);
-       DESCRIPTOR_ASSERT(pool);
+       assert(pool);
 
        pool->referer = referer;
        pool->fieldcount = 0;
@@ -387,12 +451,12 @@ 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(stderr,name);fprintf(stderr,")\n");
+       utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
 #endif
 
        /* find a place in the hashtable */
@@ -457,11 +521,11 @@ 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
 
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT(desc);
+       assert(pool);
+       assert(desc);
 
        /* find a place in the hashtable */
 
@@ -548,6 +612,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,
@@ -593,7 +658,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);
@@ -636,9 +701,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);
@@ -650,7 +715,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;
 }
 
@@ -673,7 +738,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.                                */
@@ -723,9 +788,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 */
 
@@ -743,7 +808,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,
@@ -803,12 +868,20 @@ 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
 
-       DESCRIPTOR_ASSERT(pool);
-       DESCRIPTOR_ASSERT(pool->descriptors);
-       DESCRIPTOR_ASSERT(pool->descriptors_next);
+       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 */
 
@@ -825,20 +898,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 */
@@ -861,7 +928,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++;
@@ -905,13 +972,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;
        }
 
@@ -948,9 +1023,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;
 
@@ -961,7 +1036,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 */
@@ -985,16 +1060,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;
 }
@@ -1023,8 +1104,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;
@@ -1055,17 +1136,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
@@ -1086,9 +1172,9 @@ 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>");
        }
@@ -1191,7 +1277,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);
@@ -1207,7 +1293,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;
                }
@@ -1218,7 +1304,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;
                }
@@ -1262,6 +1348,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.