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