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