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