Merged with tip.
[cacao.git] / src / vmcore / descriptor.c
1 /* src/vmcore/descriptor.c - checking and parsing of field / method descriptors
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29
30 #include "vm/types.h"
31
32 #include "md-abi.h"
33
34 #include "mm/memory.h"
35
36 #include "vm/exceptions.h"
37 #include "vm/jit_interface.h"
38 #include "vm/primitive.hpp"
39 #include "vm/vm.h"
40
41 #include "vmcore/descriptor.h"
42 #include "vmcore/options.h"
43
44
45 /* constants (private to descriptor.c) ****************************************/
46
47 /* initial number of entries for the classrefhash of a descriptor_pool */
48 /* (currently the hash is never grown!) */
49 #define CLASSREFHASH_INIT_SIZE  64
50
51 /* initial number of entries for the descriptorhash of a descriptor_pool */
52 /* (currently the hash is never grown!) */
53 #define DESCRIPTORHASH_INIT_SIZE  128
54
55 /* data structures (private to descriptor.c) **********************************/
56
57 typedef struct classref_hash_entry classref_hash_entry;
58 typedef struct descriptor_hash_entry descriptor_hash_entry;
59
60 /* entry struct for the classrefhash of descriptor_pool */
61 struct classref_hash_entry {
62         classref_hash_entry *hashlink;  /* for hash chaining            */
63         utf                 *name;      /* name of the class refered to */
64         u2                   index;     /* index into classref table    */
65 };
66
67 /* entry struct for the descriptorhash of descriptor_pool */
68 struct descriptor_hash_entry {
69         descriptor_hash_entry *hashlink;
70         utf                   *desc;
71         parseddesc_t           parseddesc;
72         s2                     paramslots; /* number of params, LONG/DOUBLE counted as 2 */
73 };
74
75
76 /****************************************************************************/
77 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c)                  */
78 /****************************************************************************/
79
80 /* SKIP_FIELDDESCRIPTOR:
81  * utf_ptr must point to the first character of a field descriptor.
82  * After the macro call utf_ptr points to the first character after
83  * the field descriptor.
84  *
85  * CAUTION: This macro does not check for an unexpected end of the
86  * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
87  */
88 #define SKIP_FIELDDESCRIPTOR(utf_ptr)                                                   \
89         do { while (*(utf_ptr)=='[') (utf_ptr)++;                                       \
90                 if (*(utf_ptr)++=='L')                                                                  \
91                         while(*(utf_ptr)++ != ';') /* skip */; } while(0)
92
93 /* SKIP_FIELDDESCRIPTOR_SAFE:
94  * utf_ptr must point to the first character of a field descriptor.
95  * After the macro call utf_ptr points to the first character after
96  * the field descriptor.
97  *
98  * Input:
99  *     utf_ptr....points to first char of descriptor
100  *     end_ptr....points to first char after the end of the string
101  *     errorflag..must be initialized (to false) by the caller!
102  * Output:
103  *     utf_ptr....points to first char after the descriptor
104  *     errorflag..set to true if the string ended unexpectedly
105  */
106 #define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag)                    \
107         do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++;     \
108                 if ((utf_ptr) == (end_ptr))                                                                             \
109                         (errorflag) = true;                                                                                     \
110                 else                                                                                                                    \
111                         if (*(utf_ptr)++=='L') {                                                                        \
112                                 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';')    \
113                                         /* skip */;                                                                                     \
114                                 if ((utf_ptr)[-1] != ';')                                                               \
115                                         (errorflag) = true; }} while(0)
116
117
118 /****************************************************************************/
119 /* DEBUG HELPERS                                                            */
120 /****************************************************************************/
121
122 /*#define DESCRIPTOR_VERBOSE*/
123
124 /****************************************************************************/
125 /* FUNCTIONS                                                                */
126 /****************************************************************************/
127
128 /* descriptor_to_basic_type ****************************************************
129
130    Return the basic type to use for a value with this descriptor.
131
132    IN:
133        utf..............descriptor utf string
134
135    OUT:
136        A TYPE_* constant.
137
138    PRECONDITIONS:
139        This function assumes that the descriptor has passed 
140            descriptor_pool_add checks and that it does not start with '('.
141
142 *******************************************************************************/
143
144 int descriptor_to_basic_type(utf *descriptor)
145 {
146         assert(descriptor->blength >= 1);
147         
148         switch (descriptor->text[0]) {
149         case 'Z':
150         case 'B':
151         case 'C':
152         case 'S':
153         case 'I':
154                 return TYPE_INT;
155
156         case 'J':
157                 return TYPE_LNG;
158
159         case 'F':
160                 return TYPE_FLT;
161
162         case 'D':
163                 return TYPE_DBL;
164
165         case 'L':
166         case '[':
167                 return TYPE_ADR;
168
169         default:
170                 vm_abort("descriptor_to_basic_type: invalid type %c",
171                                  descriptor->text[0]);
172         }
173
174         /* keep the compiler happy */
175
176         return 0;
177 }
178
179
180 /* descriptor_typesize *********************************************************
181
182    Return the size in bytes needed for the given type.
183
184    IN:
185        td..............typedesc describing the type
186
187    OUT:
188        The number of bytes
189
190 *******************************************************************************/
191
192 int descriptor_typesize(typedesc *td)
193 {
194         assert(td);
195
196         switch (td->type) {
197         case TYPE_INT:
198         case TYPE_FLT:
199                 return 4;
200
201         case TYPE_LNG:
202         case TYPE_DBL:
203                 return 8;
204
205         case TYPE_ADR:
206                 return SIZEOF_VOID_P;
207
208         default:
209                 vm_abort("descriptor_typesize: invalid type %d", td->type);
210         }
211
212         /* keep the compiler happy */
213
214         return 0;
215 }
216
217
218 /* name_from_descriptor ********************************************************
219
220    Return the class name indicated by the given descriptor
221    (Internally used helper function)
222
223    IN:
224        c................class containing the descriptor
225        utf_ptr..........first character of descriptor
226        end_ptr..........first character after the end of the string
227        mode.............a combination (binary or) of the following flags:
228
229                (Flags marked with * are the default settings.)
230
231                How to handle "V" descriptors:
232
233                              * DESCRIPTOR_VOID.....handle it like other primitive types
234                    DESCRIPTOR_NOVOID...treat it as an error
235
236                How to deal with extra characters after the end of the
237                descriptor:
238
239                              * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
240                    DESCRIPTOR_CHECKEND.....treat them as an error
241
242    OUT:
243        *next............if non-NULL, *next is set to the first character after
244                         the descriptor. (Undefined if an error occurs.)
245        *name............set to the utf name of the class
246
247    RETURN VALUE:
248        true.............descriptor parsed successfully
249            false............an exception has been thrown
250
251 *******************************************************************************/
252
253 #define DESCRIPTOR_VOID          0      /* default */
254 #define DESCRIPTOR_NOVOID        0x0040
255 #define DESCRIPTOR_NOCHECKEND    0      /* default */
256 #define DESCRIPTOR_CHECKEND      0x1000
257
258 static bool 
259 name_from_descriptor(classinfo *c,
260                                          char *utf_ptr, char *end_ptr,
261                                          char **next, int mode, utf **name)
262 {
263         char *start = utf_ptr;
264         bool error = false;
265
266         assert(c);
267         assert(utf_ptr);
268         assert(end_ptr);
269         assert(name);
270         
271         *name = NULL;           
272         SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
273
274         if (mode & DESCRIPTOR_CHECKEND)
275                 error |= (utf_ptr != end_ptr);
276         
277         if (!error) {
278                 if (next) *next = utf_ptr;
279                 
280                 switch (*start) {
281                   case 'V':
282                           if (mode & DESCRIPTOR_NOVOID)
283                                   break;
284                           /* FALLTHROUGH! */
285                   case 'I':
286                   case 'J':
287                   case 'F':
288                   case 'D':
289                   case 'B':
290                   case 'C':
291                   case 'S':
292                   case 'Z':
293                           return true;
294                           
295                   case 'L':
296                           start++;
297                           utf_ptr--;
298                           /* FALLTHROUGH! */
299                   case '[':
300                           *name = utf_new(start, utf_ptr - start);
301                           return true;
302                 }
303         }
304
305         exceptions_throw_classformaterror(c, "Invalid descriptor");
306         return false;
307 }
308
309
310 /* descriptor_to_typedesc ******************************************************
311  
312    Parse the given type descriptor and fill a typedesc struct
313    (Internally used helper function)
314
315    IN:
316        pool.............the descriptor pool
317            utf_ptr..........points to first character of type descriptor
318            end_pos..........points after last character of the whole descriptor
319
320    OUT:
321        *next............set to next character after type descriptor
322            *d...............filled with parsed information
323
324    RETURN VALUE:
325        true.............parsing succeeded  
326            false............an exception has been thrown
327
328 *******************************************************************************/
329
330 static bool
331 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
332                                            char **next, typedesc *td)
333 {
334         utf *name;
335         
336         if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
337                 return false;
338
339         if (name) {
340                 /* a reference type */
341                 td->type = TYPE_ADR;
342                 td->decltype = TYPE_ADR;
343                 td->arraydim = 0;
344                 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
345                         td->arraydim++;
346                 td->classref = descriptor_pool_lookup_classref(pool, name);
347
348         } else {
349                 /* a primitive type */
350                 switch (*utf_ptr) {
351                 case 'B': 
352                         td->decltype = PRIMITIVETYPE_BYTE;
353                         td->type = TYPE_INT;
354                         break;
355                 case 'C':
356                         td->decltype = PRIMITIVETYPE_CHAR;
357                         td->type = TYPE_INT;
358                         break;
359                 case 'S':  
360                         td->decltype = PRIMITIVETYPE_SHORT;
361                         td->type = TYPE_INT;
362                         break;
363                 case 'Z':
364                         td->decltype = PRIMITIVETYPE_BOOLEAN;
365                         td->type = TYPE_INT;
366                         break;
367                 case 'I':
368                         td->decltype = PRIMITIVETYPE_INT;
369                         td->type = TYPE_INT;
370                         break;
371                 case 'D':
372                         td->decltype = PRIMITIVETYPE_DOUBLE;
373                         td->type = TYPE_DBL;
374                         break;
375                 case 'F':
376                         td->decltype = PRIMITIVETYPE_FLOAT;
377                         td->type = TYPE_FLT;
378                         break;
379                 case 'J':
380                         td->decltype = PRIMITIVETYPE_LONG;
381                         td->type = TYPE_LNG;
382                         break;
383                 case 'V':
384                         td->decltype = PRIMITIVETYPE_VOID;
385                         td->type = TYPE_VOID;
386                         break;
387                 default:
388                         assert(false);
389                 }
390
391                 td->arraydim = 0;
392                 td->classref = NULL;
393         }
394
395         return true;
396 }
397
398
399 /* descriptor_pool_new *********************************************************
400  
401    Allocate a new descriptor_pool
402
403    IN:
404        referer..........class for which to create the pool
405
406    RETURN VALUE:
407        a pointer to the new descriptor_pool
408
409 *******************************************************************************/
410
411 descriptor_pool * 
412 descriptor_pool_new(classinfo *referer)
413 {
414         descriptor_pool *pool;
415         u4 hashsize;
416         u4 slot;
417
418         pool = DNEW(descriptor_pool);
419         assert(pool);
420
421         pool->referer = referer;
422         pool->fieldcount = 0;
423         pool->methodcount = 0;
424         pool->paramcount = 0;
425         pool->descriptorsize = 0;
426         pool->descriptors = NULL;
427         pool->descriptors_next = NULL;
428         pool->classrefs = NULL;
429         pool->descriptor_kind = NULL;
430         pool->descriptor_kind_next = NULL;
431
432         hashsize = CLASSREFHASH_INIT_SIZE;
433         pool->classrefhash.size = hashsize;
434         pool->classrefhash.entries = 0;
435         pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
436         for (slot=0; slot<hashsize; ++slot)
437                 pool->classrefhash.ptr[slot] = NULL;
438
439         hashsize = DESCRIPTORHASH_INIT_SIZE;
440         pool->descriptorhash.size = hashsize;
441         pool->descriptorhash.entries = 0;
442         pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
443         for (slot=0; slot<hashsize; ++slot)
444                 pool->descriptorhash.ptr[slot] = NULL;
445
446         return pool;
447 }
448
449
450 /* descriptor_pool_add_class ***************************************************
451  
452    Add the given class reference to the pool
453
454    IN:
455        pool.............the descriptor_pool
456            name.............the class reference to add
457
458    RETURN VALUE:
459        true.............reference has been added
460            false............an exception has been thrown
461
462 *******************************************************************************/
463
464 bool 
465 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
466 {
467         u4 key,slot;
468         classref_hash_entry *c;
469         
470         assert(pool);
471         assert(name);
472
473 #ifdef DESCRIPTOR_VERBOSE
474         fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
475         utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
476 #endif
477
478         /* find a place in the hashtable */
479
480         key = utf_hashkey(name->text, name->blength);
481         slot = key & (pool->classrefhash.size - 1);
482         c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
483
484         while (c) {
485                 if (c->name == name)
486                         return true; /* already stored */
487                 c = c->hashlink;
488         }
489
490         /* check if the name is a valid classname */
491
492         if (!is_valid_name(name->text,UTF_END(name))) {
493                 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
494                 return false; /* exception */
495         }
496
497         /* XXX check maximum array dimension */
498         
499         c = DNEW(classref_hash_entry);
500         c->name = name;
501         c->index = pool->classrefhash.entries++;
502         c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
503         pool->classrefhash.ptr[slot] = c;
504
505         return true;
506 }
507
508
509 /* descriptor_pool_add *********************************************************
510  
511    Check the given descriptor and add it to the pool
512
513    IN:
514        pool.............the descriptor_pool
515            desc.............the descriptor to add. Maybe a field or method desc.
516
517    OUT:
518        *paramslots......if non-NULL, set to the number of parameters.
519                             LONG and DOUBLE are counted twice
520
521    RETURN VALUE:
522        true.............descriptor has been added
523            false............an exception has been thrown
524
525 *******************************************************************************/
526
527 bool 
528 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
529 {
530         u4 key,slot;
531         descriptor_hash_entry *d;
532         char *utf_ptr;
533         char *end_pos;
534         utf *name;
535         s4 argcount = 0;
536         
537 #ifdef DESCRIPTOR_VERBOSE
538         fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
539         utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
540 #endif
541
542         assert(pool);
543         assert(desc);
544
545         /* find a place in the hashtable */
546
547         key = utf_hashkey(desc->text, desc->blength);
548         slot = key & (pool->descriptorhash.size - 1);
549         d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
550
551         /* Save all method descriptors in the hashtable, since the parsed         */
552         /* descriptor may vary between differenf methods (static vs. non-static). */
553
554         utf_ptr = desc->text;
555
556         if (*utf_ptr != '(') {
557                 while (d) {
558                         if (d->desc == desc) {
559                                 if (paramslots)
560                                         *paramslots = d->paramslots;
561                                 return true; /* already stored */
562                         }
563                         d = d->hashlink;
564                 }
565         }
566
567         /* add the descriptor to the pool */
568
569         d = DNEW(descriptor_hash_entry);
570         d->desc = desc;
571         d->parseddesc.any = NULL;
572         d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
573         pool->descriptorhash.ptr[slot] = d;
574
575         /* now check the descriptor */
576
577         end_pos = UTF_END(desc);
578         
579         if (*utf_ptr == '(') {
580                 /* a method descriptor */
581
582                 pool->methodcount++;
583                 utf_ptr++;
584
585                 /* check arguments */
586
587                 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
588                         pool->paramcount++;
589
590                         /* We cannot count the `this' argument here because
591                          * we don't know if the method is static. */
592
593                         if (*utf_ptr == 'J' || *utf_ptr == 'D')
594                                 argcount += 2;
595                         else
596                                 argcount++;
597
598                         if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
599                                                                       DESCRIPTOR_NOVOID, &name))
600                                 return false;
601
602                         if (name)
603                                 if (!descriptor_pool_add_class(pool, name))
604                                         return false;
605                 }
606
607                 if (utf_ptr == end_pos) {
608                         exceptions_throw_classformaterror(pool->referer,
609                                                                                           "Missing ')' in method descriptor");
610                         return false;
611                 }
612
613                 utf_ptr++; /* skip ')' */
614
615                 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
616                                                                   DESCRIPTOR_CHECKEND, &name))
617                         return false;
618
619                 if (name)
620                         if (!descriptor_pool_add_class(pool,name))
621                                 return false;
622
623                 if (argcount > 255) {
624                         exceptions_throw_classformaterror(pool->referer,
625                                                                                           "Too many arguments in signature");
626                         return false;
627                 }
628
629         } else {
630                 /* a field descriptor */
631
632                 pool->fieldcount++;
633                 
634             if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
635                                                           DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
636                                                                   &name))
637                         return false;
638
639                 if (name)
640                         if (!descriptor_pool_add_class(pool,name))
641                                 return false;
642         }
643
644         d->paramslots = argcount;
645
646         if (paramslots)
647                 *paramslots = argcount;
648
649         return true;
650 }
651
652
653 /* descriptor_pool_create_classrefs ********************************************
654  
655    Create a table containing all the classrefs which were added to the pool
656
657    IN:
658        pool.............the descriptor_pool
659
660    OUT:
661        *count...........if count is non-NULL, this is set to the number
662                             of classrefs in the table
663
664    RETURN VALUE:
665        a pointer to the constant_classref table
666
667 *******************************************************************************/
668
669 constant_classref * 
670 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
671 {
672         u4 nclasses;
673         u4 slot;
674         classref_hash_entry *c;
675         constant_classref *ref;
676         
677         assert(pool);
678
679         nclasses = pool->classrefhash.entries;
680         pool->classrefs = MNEW(constant_classref,nclasses);
681
682         /* fill the constant_classref structs */
683
684         for (slot = 0; slot < pool->classrefhash.size; ++slot) {
685                 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
686                 while (c) {
687                         ref = pool->classrefs + c->index;
688                         CLASSREF_INIT(*ref, pool->referer, c->name);
689                         c = c->hashlink;
690                 }
691         }
692
693         if (count)
694                 *count = nclasses;
695
696         return pool->classrefs;
697 }
698
699
700 /* descriptor_pool_lookup_classref *********************************************
701  
702    Return the constant_classref for the given class name
703
704    IN:
705        pool.............the descriptor_pool
706            classname........name of the class to look up
707
708    RETURN VALUE:
709        a pointer to the constant_classref, or
710            NULL if an exception has been thrown
711
712 *******************************************************************************/
713
714 constant_classref * 
715 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
716 {
717         u4 key,slot;
718         classref_hash_entry *c;
719
720         assert(pool);
721         assert(pool->classrefs);
722         assert(classname);
723
724         key = utf_hashkey(classname->text, classname->blength);
725         slot = key & (pool->classrefhash.size - 1);
726         c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
727
728         while (c) {
729                 if (c->name == classname)
730                         return pool->classrefs + c->index;
731                 c = c->hashlink;
732         }
733
734         exceptions_throw_internalerror("Class reference not found in descriptor pool");
735         return NULL;
736 }
737
738
739 /* descriptor_pool_alloc_parsed_descriptors ************************************
740  
741    Allocate space for the parsed descriptors
742
743    IN:
744        pool.............the descriptor_pool
745
746    NOTE:
747        This function must be called after all descriptors have been added
748            with descriptor_pool_add.
749
750 *******************************************************************************/
751
752 void 
753 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
754 {
755         u4 size;
756         
757         assert(pool);
758
759         /* TWISTI: paramcount + 1: we don't know if the method is static or   */
760         /* not, i have no better solution yet.                                */
761
762         size =
763                 pool->fieldcount * sizeof(typedesc) +
764                 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
765                 pool->paramcount * sizeof(typedesc) +
766                 pool->methodcount * sizeof(typedesc);      /* possible `this' pointer */
767
768         pool->descriptorsize = size;
769         if (size) {
770                 pool->descriptors = MNEW(u1, size);
771                 pool->descriptors_next = pool->descriptors;
772         }
773
774         size = pool->fieldcount + pool->methodcount;
775         if (size) {
776                 pool->descriptor_kind = DMNEW(u1, size);
777                 pool->descriptor_kind_next = pool->descriptor_kind;
778         }
779 }
780
781
782 /* descriptor_pool_parse_field_descriptor **************************************
783  
784    Parse the given field descriptor
785
786    IN:
787        pool.............the descriptor_pool
788            desc.............the field descriptor
789
790    RETURN VALUE:
791        a pointer to the parsed field descriptor, or
792            NULL if an exception has been thrown
793
794    NOTE:
795        descriptor_pool_alloc_parsed_descriptors must be called (once)
796        before this function is used.
797
798 *******************************************************************************/
799
800 typedesc * 
801 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
802 {
803         u4 key,slot;
804         descriptor_hash_entry *d;
805         typedesc *td;
806
807         assert(pool);
808         assert(pool->descriptors);
809         assert(pool->descriptors_next);
810
811         /* lookup the descriptor in the hashtable */
812
813         key = utf_hashkey(desc->text, desc->blength);
814         slot = key & (pool->descriptorhash.size - 1);
815         d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
816
817         while (d) {
818                 if (d->desc == desc) {
819                         /* found */
820                         if (d->parseddesc.fd)
821                                 return d->parseddesc.fd;
822                         break;
823                 }
824                 d = d->hashlink;
825         }
826
827         assert(d);
828         
829         if (desc->text[0] == '(') {
830                 exceptions_throw_classformaterror(pool->referer,
831                                                                                   "Method descriptor used in field reference");
832                 return NULL;
833         }
834
835         td = (typedesc *) pool->descriptors_next;
836         pool->descriptors_next += sizeof(typedesc);
837         
838         if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
839                 return NULL;
840
841         *(pool->descriptor_kind_next++) = 'f';
842
843         d->parseddesc.fd = td;
844
845         return td;
846 }
847
848
849 /* descriptor_pool_parse_method_descriptor *************************************
850  
851    Parse the given method descriptor
852
853    IN:
854        pool.............the descriptor_pool
855        desc.............the method descriptor
856        mflags...........the method flags
857            thisclass........classref to the class containing the method.
858                                                 This is ignored if mflags contains ACC_STATIC.
859                                                 The classref is stored for inserting the 'this' argument.
860
861    RETURN VALUE:
862        a pointer to the parsed method descriptor, or
863            NULL if an exception has been thrown
864
865    NOTE: 
866        descriptor_pool_alloc_parsed_descriptors must be called
867        (once) before this function is used.
868
869 *******************************************************************************/
870
871 methoddesc * 
872 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
873                                                                                 s4 mflags,constant_classref *thisclass)
874 {
875         u4 key, slot;
876         descriptor_hash_entry *d;
877         methoddesc            *md;
878         typedesc              *td;
879         char *utf_ptr;
880         char *end_pos;
881         s2 paramcount = 0;
882         s2 paramslots = 0;
883
884 #ifdef DESCRIPTOR_VERBOSE
885         fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
886                         (void*)pool,(int)mflags,(void*)thisclass);
887         utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
888 #endif
889
890         assert(pool);
891         assert(pool->descriptors);
892         assert(pool->descriptors_next);
893
894         /* check that it is a method descriptor */
895         
896         if (desc->text[0] != '(') {
897                 exceptions_throw_classformaterror(pool->referer,
898                                                                                   "Field descriptor used in method reference");
899                 return NULL;
900         }
901
902         /* lookup the descriptor in the hashtable */
903
904         key = utf_hashkey(desc->text, desc->blength);
905         slot = key & (pool->descriptorhash.size - 1);
906         d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
907
908         /* find an un-parsed descriptor */
909
910         while (d) {
911                 if (d->desc == desc)
912                         if (!d->parseddesc.md)
913                                 break;
914                 d = d->hashlink;
915         }
916
917         assert(d);
918
919         md = (methoddesc *) pool->descriptors_next;
920         pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
921
922         utf_ptr = desc->text + 1; /* skip '(' */
923         end_pos = UTF_END(desc);
924
925         td = md->paramtypes;
926
927         /* count the `this' pointer */
928
929         if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
930                 td->type = TYPE_ADR;
931                 td->decltype = TYPE_ADR;
932                 td->arraydim = 0;
933                 td->classref = thisclass;
934
935                 td++;
936                 pool->descriptors_next += sizeof(typedesc);
937                 paramcount++;
938                 paramslots++;
939         }
940
941         while (*utf_ptr != ')') {
942                 /* parse a parameter type */
943
944                 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
945                         return NULL;
946
947                 if (IS_2_WORD_TYPE(td->type))
948                         paramslots++;
949                 
950                 td++;
951                 pool->descriptors_next += sizeof(typedesc);
952                 paramcount++;
953                 paramslots++;
954         }
955         utf_ptr++; /* skip ')' */
956
957         /* Skip possible `this' pointer in paramtypes array to allow a possible   */
958         /* memory move later in parse.                                            */
959         /* We store the thisclass reference, so we can later correctly fill in    */
960         /* the parameter slot of the 'this' argument.                             */
961
962         if (mflags == ACC_UNDEF) {
963                 td->classref = thisclass;
964                 td++;
965                 pool->descriptors_next += sizeof(typedesc);
966         }
967
968         /* parse return type */
969
970         if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
971                                                                 &(md->returntype)))
972                 return NULL;
973
974         md->paramcount = paramcount;
975         md->paramslots = paramslots;
976
977         /* If mflags != ACC_UNDEF we parse a real loaded method, so do
978            param prealloc.  Otherwise we do this in stack analysis. */
979
980         if (mflags != ACC_UNDEF) {
981                 if (md->paramcount > 0) {
982                         /* allocate memory for params */
983
984                         md->params = MNEW(paramdesc, md->paramcount);
985                 }
986                 else {
987                         md->params = METHODDESC_NOPARAMS;
988                 }
989
990                 /* fill the paramdesc */
991                 /* md_param_alloc has to be called if md->paramcount == 0,
992                    too, so it can make the reservation for the Linkage Area,
993                    Return Register... */
994
995 #if defined(ENABLE_JIT)
996 # if defined(ENABLE_INTRP)
997                 if (!opt_intrp)
998 # endif
999                         {
1000                                 /* As builtin-functions are native functions, we have
1001                                    to pre-allocate for the native ABI. */
1002
1003                                 if (mflags & ACC_METHOD_BUILTIN)
1004                                         md_param_alloc_native(md);
1005                                 else
1006                                         md_param_alloc(md);
1007                         }
1008 #endif
1009         }
1010         else {
1011                 /* params will be allocated later by
1012                    descriptor_params_from_paramtypes if necessary */
1013
1014                 md->params = NULL;
1015         }
1016
1017         *(pool->descriptor_kind_next++) = 'm';
1018
1019         d->parseddesc.md = md;
1020
1021         return md;
1022 }
1023
1024 /* descriptor_params_from_paramtypes *******************************************
1025  
1026    Create the paramdescs for a method descriptor. This function is called
1027    when we know whether the method is static or not. This function may only
1028    be called once for each methoddesc, and only if md->params == NULL.
1029
1030    IN:
1031        md...............the parsed method descriptor
1032                             md->params MUST be NULL.
1033            mflags...........the ACC_* access flags of the method. Only the
1034                             ACC_STATIC bit is checked.
1035                                                 The value ACC_UNDEF is NOT allowed.
1036
1037    RETURN VALUE:
1038        true.............the paramdescs were created successfully
1039            false............an exception has been thrown
1040
1041    POSTCONDITION:
1042        md->parms != NULL
1043
1044 *******************************************************************************/
1045
1046 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1047 {
1048         typedesc *td;
1049
1050         assert(md);
1051         assert(md->params == NULL);
1052         assert(mflags != ACC_UNDEF);
1053
1054         td = md->paramtypes;
1055
1056         /* check for `this' pointer */
1057
1058         if (!(mflags & ACC_STATIC)) {
1059                 constant_classref *thisclass;
1060
1061                 /* fetch class reference from reserved param slot */
1062                 thisclass = td[md->paramcount].classref;
1063                 assert(thisclass);
1064
1065                 if (md->paramcount > 0) {
1066                         /* shift param types by 1 argument */
1067                         MMOVE(td + 1, td, typedesc, md->paramcount);
1068                 }
1069
1070                 /* fill in first argument `this' */
1071
1072                 td->type = TYPE_ADR;
1073                 td->decltype = TYPE_ADR;
1074                 td->arraydim = 0;
1075                 td->classref = thisclass;
1076
1077                 md->paramcount++;
1078                 md->paramslots++;
1079         }
1080
1081         /* if the method has params, process them */
1082
1083         if (md->paramcount > 0) {
1084                 /* allocate memory for params */
1085
1086                 md->params = MNEW(paramdesc, md->paramcount);
1087
1088         } else {
1089                 md->params = METHODDESC_NOPARAMS;
1090         }
1091
1092         /* fill the paramdesc */
1093         /* md_param_alloc has to be called if md->paramcount == 0, too, so
1094            it can make the reservation for the Linkage Area, Return
1095            Register.. */
1096
1097 #if defined(ENABLE_JIT)
1098 # if defined(ENABLE_INTRP)
1099         if (!opt_intrp)
1100 # endif
1101                 {
1102                         /* As builtin-functions are native functions, we have to
1103                            pre-allocate for the native ABI. */
1104
1105                         if (mflags & ACC_METHOD_BUILTIN)
1106                                 md_param_alloc_native(md);
1107                         else
1108                                 md_param_alloc(md);
1109                 }
1110 #endif
1111
1112         return true;
1113 }
1114
1115
1116 /* descriptor_pool_get_parsed_descriptors **************************************
1117  
1118    Return a pointer to the block of parsed descriptors
1119
1120    IN:
1121        pool.............the descriptor_pool
1122
1123    OUT:
1124            *size............if size is non-NULL, this is set to the size of the
1125                             parsed descriptor block (in u1)
1126
1127    RETURN VALUE:
1128        a pointer to the block of parsed descriptors
1129
1130    NOTE:
1131        descriptor_pool_alloc_parsed_descriptors must be called (once)
1132        before this function is used.
1133
1134 *******************************************************************************/
1135
1136 void * 
1137 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1138 {
1139         assert(pool);
1140         assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1141         
1142         if (size)
1143                 *size = pool->descriptorsize;
1144
1145         return pool->descriptors;
1146 }
1147
1148
1149 /* descriptor_pool_get_sizes ***************************************************
1150  
1151    Get the sizes of the class reference table and the parsed descriptors
1152
1153    IN:
1154        pool.............the descriptor_pool
1155
1156    OUT:
1157        *classrefsize....set to size of the class reference table
1158            *descsize........set to size of the parsed descriptors
1159
1160    NOTE:
1161        This function may only be called after both
1162                descriptor_pool_create_classrefs, and
1163                    descriptor_pool_alloc_parsed_descriptors
1164            have been called.
1165
1166 *******************************************************************************/
1167
1168 void 
1169 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1170 {
1171         assert(pool);
1172         assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1173         assert(pool->classrefs);
1174         assert(classrefsize);
1175         assert(descsize);
1176
1177         *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1178         *descsize = pool->descriptorsize;
1179 }
1180
1181
1182 /****************************************************************************/
1183 /* DEBUG HELPERS                                                            */
1184 /****************************************************************************/
1185
1186 #ifndef NDEBUG
1187 /* descriptor_debug_print_typedesc *********************************************
1188  
1189    Print the given typedesc to the given stream
1190
1191    IN:
1192            file.............stream to print to
1193            d................the parsed descriptor
1194
1195 *******************************************************************************/
1196
1197 void 
1198 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1199 {
1200         int ch;
1201
1202         if (!d) {
1203                 fprintf(file,"(typedesc *)NULL");
1204                 return;
1205         }
1206         
1207         if (d->type == TYPE_ADR) {
1208                 if (d->classref)
1209                         utf_fprint_printable_ascii(file,d->classref->name);
1210                 else
1211                         fprintf(file,"<class=NULL>");
1212         }
1213         else {
1214                 switch (d->decltype) {
1215                         case PRIMITIVETYPE_INT    : ch='I'; break;
1216                         case PRIMITIVETYPE_CHAR   : ch='C'; break;
1217                         case PRIMITIVETYPE_BYTE   : ch='B'; break;
1218                         case PRIMITIVETYPE_SHORT  : ch='S'; break;
1219                         case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1220                         case PRIMITIVETYPE_LONG   : ch='J'; break;
1221                         case PRIMITIVETYPE_FLOAT  : ch='F'; break;
1222                         case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1223                         case PRIMITIVETYPE_VOID   : ch='V'; break;
1224                         default                   : ch='!';
1225                 }
1226                 fputc(ch,file);
1227         }
1228         if (d->arraydim)
1229                 fprintf(file,"[%d]",d->arraydim);
1230 }
1231
1232 /* descriptor_debug_print_paramdesc ********************************************
1233  
1234    Print the given paramdesc to the given stream
1235
1236    IN:
1237            file.............stream to print to
1238            d................the parameter descriptor
1239
1240 *******************************************************************************/
1241
1242 void
1243 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1244 {
1245         if (!d) {
1246                 fprintf(file,"(paramdesc *)NULL");
1247                 return;
1248         }
1249         
1250         if (d->inmemory) {
1251                 fprintf(file,"<m%d>",d->regoff);
1252         }
1253         else {
1254                 fprintf(file,"<r%d>",d->regoff);
1255         }
1256 }
1257
1258 /* descriptor_debug_print_methoddesc *******************************************
1259  
1260    Print the given methoddesc to the given stream
1261
1262    IN:
1263            file.............stream to print to
1264            d................the parsed descriptor
1265
1266 *******************************************************************************/
1267
1268 void 
1269 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1270 {
1271         int i;
1272         
1273         if (!d) {
1274                 fprintf(file,"(methoddesc *)NULL");
1275                 return;
1276         }
1277         
1278         fputc('(',file);
1279         for (i=0; i<d->paramcount; ++i) {
1280                 if (i)
1281                         fputc(',',file);
1282                 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1283                 if (d->params) {
1284                         descriptor_debug_print_paramdesc(file,d->params + i);
1285                 }
1286         }
1287         if (d->params == METHODDESC_NOPARAMS)
1288                 fputs("<NOPARAMS>",file);
1289         fputc(')',file);
1290         descriptor_debug_print_typedesc(file,&(d->returntype));
1291 }
1292
1293 /* descriptor_pool_debug_dump **************************************************
1294  
1295    Print the state of the descriptor_pool to the given stream
1296
1297    IN:
1298        pool.............the descriptor_pool
1299            file.............stream to print to
1300
1301 *******************************************************************************/
1302
1303 void 
1304 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1305 {
1306         u4 slot;
1307         u1 *pos;
1308         u1 *kind;
1309         u4 size;
1310         
1311         fprintf(file,"======[descriptor_pool for ");
1312         utf_fprint_printable_ascii(file,pool->referer->name);
1313         fprintf(file,"]======\n");
1314
1315         fprintf(file,"fieldcount:     %d\n",pool->fieldcount);
1316         fprintf(file,"methodcount:    %d\n",pool->methodcount);
1317         fprintf(file,"paramcount:     %d\n",pool->paramcount);
1318         fprintf(file,"classrefcount:  %d\n",pool->classrefhash.entries);
1319         fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1320         fprintf(file,"classrefsize:   %d bytes\n",
1321                         (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1322
1323         fprintf(file,"class references:\n");
1324         for (slot=0; slot<pool->classrefhash.size; ++slot) {
1325                 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1326                 while (c) {
1327                         fprintf(file,"    %4d: ",c->index);
1328                         utf_fprint_printable_ascii(file,c->name);
1329                         fprintf(file,"\n");
1330                         c = c->hashlink;
1331                 }
1332         }
1333
1334         fprintf(file,"hashed descriptors:\n");
1335         for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1336                 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1337                 while (c) {
1338                         fprintf(file,"    %p: ",c->parseddesc.any);
1339                         utf_fprint_printable_ascii(file,c->desc);
1340                         fprintf(file,"\n");
1341                         c = c->hashlink;
1342                 }
1343         }
1344
1345         fprintf(file,"descriptors:\n");
1346         if (pool->descriptors) {
1347                 pos = pool->descriptors;
1348                 size = pool->descriptors_next - pool->descriptors;
1349                 fprintf(file,"    size: %d bytes\n",size);
1350                 
1351                 if (pool->descriptor_kind) {
1352                         kind = pool->descriptor_kind;
1353
1354                         while (pos < (pool->descriptors + size)) {
1355                                 fprintf(file,"    %p: ",pos);
1356                                 switch (*kind++) {
1357                                         case 'f':
1358                                                 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1359                                                 pos += sizeof(typedesc);
1360                                                 break;
1361                                         case 'm':
1362                                                 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1363                                                 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1364                                                 pos += sizeof(methoddesc) - sizeof(typedesc);
1365                                                 break;
1366                                         default:
1367                                                 fprintf(file,"INVALID KIND");
1368                                 }
1369                                 fputc('\n',file);
1370                         }
1371                 }
1372                 else {
1373                         while (size >= sizeof(voidptr)) {
1374                                 fprintf(file,"    %p\n",*((voidptr*)pos));
1375                                 pos += sizeof(voidptr);
1376                                 size -= sizeof(voidptr);
1377                         }
1378                 }
1379         }
1380
1381         fprintf(file,"==========================================================\n");
1382 }
1383 #endif /* !defined(NDEBUG) */
1384
1385 /*
1386  * These are local overrides for various environment variables in Emacs.
1387  * Please do not remove this and leave it at the end of the file, where
1388  * Emacs will automagically detect them.
1389  * ---------------------------------------------------------------------
1390  * Local variables:
1391  * mode: c
1392  * indent-tabs-mode: t
1393  * c-basic-offset: 4
1394  * tab-width: 4
1395  * End:
1396  * vim:noexpandtab:sw=4:ts=4:
1397  */
1398