PR163: descriptor_params_from_paramtypes is protected by a mutex now (per descriptor...
[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                 size += sizeof(Mutex);  /* prepend Mutex */
775                 pool->descriptors = MNEW(u1, size);
776                 /* call Mutex constructor */
777                 new (reinterpret_cast<Mutex*>(pool->descriptors)) Mutex;
778                 pool->descriptors += sizeof(Mutex);
779                 pool->descriptors_next = pool->descriptors;
780         }
781
782         size = pool->fieldcount + pool->methodcount;
783         if (size) {
784                 pool->descriptor_kind = (u1*) DumpMemory::allocate(sizeof(u1) * size);
785                 pool->descriptor_kind_next = pool->descriptor_kind;
786         }
787 }
788
789
790 /* descriptor_pool_parse_field_descriptor **************************************
791  
792    Parse the given field descriptor
793
794    IN:
795        pool.............the descriptor_pool
796            desc.............the field descriptor
797
798    RETURN VALUE:
799        a pointer to the parsed field descriptor, or
800            NULL if an exception has been thrown
801
802    NOTE:
803        descriptor_pool_alloc_parsed_descriptors must be called (once)
804        before this function is used.
805
806 *******************************************************************************/
807
808 typedesc * 
809 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
810 {
811         u4 key,slot;
812         descriptor_hash_entry *d;
813         typedesc *td;
814
815         assert(pool);
816         assert(pool->descriptors);
817         assert(pool->descriptors_next);
818
819         /* lookup the descriptor in the hashtable */
820
821         key = utf_hashkey(desc->text, desc->blength);
822         slot = key & (pool->descriptorhash.size - 1);
823         d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
824
825         while (d) {
826                 if (d->desc == desc) {
827                         /* found */
828                         if (d->parseddesc.fd)
829                                 return d->parseddesc.fd;
830                         break;
831                 }
832                 d = d->hashlink;
833         }
834
835         assert(d);
836         
837         if (desc->text[0] == '(') {
838                 exceptions_throw_classformaterror(pool->referer,
839                                                                                   "Method descriptor used in field reference");
840                 return NULL;
841         }
842
843         td = (typedesc *) pool->descriptors_next;
844         pool->descriptors_next += sizeof(typedesc);
845         
846         if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
847                 return NULL;
848
849         *(pool->descriptor_kind_next++) = 'f';
850
851         d->parseddesc.fd = td;
852
853         return td;
854 }
855
856
857 /* descriptor_pool_parse_method_descriptor *************************************
858  
859    Parse the given method descriptor
860
861    IN:
862        pool.............the descriptor_pool
863        desc.............the method descriptor
864        mflags...........the method flags
865            thisclass........classref to the class containing the method.
866                                                 This is ignored if mflags contains ACC_STATIC.
867                                                 The classref is stored for inserting the 'this' argument.
868
869    RETURN VALUE:
870        a pointer to the parsed method descriptor, or
871            NULL if an exception has been thrown
872
873    NOTE: 
874        descriptor_pool_alloc_parsed_descriptors must be called
875        (once) before this function is used.
876
877 *******************************************************************************/
878
879 methoddesc * 
880 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
881                                                                                 s4 mflags,constant_classref *thisclass)
882 {
883         u4 key, slot;
884         descriptor_hash_entry *d;
885         methoddesc            *md;
886         typedesc              *td;
887         char *utf_ptr;
888         char *end_pos;
889         s2 paramcount = 0;
890         s2 paramslots = 0;
891
892 #ifdef DESCRIPTOR_VERBOSE
893         fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
894                         (void*)pool,(int)mflags,(void*)thisclass);
895         utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
896 #endif
897
898         assert(pool);
899         assert(pool->descriptors);
900         assert(pool->descriptors_next);
901
902         /* check that it is a method descriptor */
903         
904         if (desc->text[0] != '(') {
905                 exceptions_throw_classformaterror(pool->referer,
906                                                                                   "Field descriptor used in method reference");
907                 return NULL;
908         }
909
910         /* lookup the descriptor in the hashtable */
911
912         key = utf_hashkey(desc->text, desc->blength);
913         slot = key & (pool->descriptorhash.size - 1);
914         d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
915
916         /* find an un-parsed descriptor */
917
918         while (d) {
919                 if (d->desc == desc)
920                         if (!d->parseddesc.md)
921                                 break;
922                 d = d->hashlink;
923         }
924
925         assert(d);
926
927         md = (methoddesc *) pool->descriptors_next;
928         md->pool_lock = reinterpret_cast<Mutex*>(pool->descriptors - sizeof(Mutex));
929         pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
930
931         utf_ptr = desc->text + 1; /* skip '(' */
932         end_pos = UTF_END(desc);
933
934         td = md->paramtypes;
935
936         /* count the `this' pointer */
937
938         if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
939                 td->type = TYPE_ADR;
940                 td->primitivetype = TYPE_ADR;
941                 td->arraydim = 0;
942                 td->classref = thisclass;
943
944                 td++;
945                 pool->descriptors_next += sizeof(typedesc);
946                 paramcount++;
947                 paramslots++;
948         }
949
950         while (*utf_ptr != ')') {
951                 /* parse a parameter type */
952
953                 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
954                         return NULL;
955
956                 if (IS_2_WORD_TYPE(td->type))
957                         paramslots++;
958                 
959                 td++;
960                 pool->descriptors_next += sizeof(typedesc);
961                 paramcount++;
962                 paramslots++;
963         }
964         utf_ptr++; /* skip ')' */
965
966         /* Skip possible `this' pointer in paramtypes array to allow a possible   */
967         /* memory move later in parse.                                            */
968         /* We store the thisclass reference, so we can later correctly fill in    */
969         /* the parameter slot of the 'this' argument.                             */
970
971         if (mflags == ACC_UNDEF) {
972                 td->classref = thisclass;
973                 td++;
974                 pool->descriptors_next += sizeof(typedesc);
975         }
976
977         /* parse return type */
978
979         if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
980                                                                 &(md->returntype)))
981                 return NULL;
982
983         md->paramcount = paramcount;
984         md->paramslots = paramslots;
985
986         /* If mflags != ACC_UNDEF we parse a real loaded method, so do
987            param prealloc.  Otherwise we do this in stack analysis. */
988
989         if (mflags != ACC_UNDEF) {
990                 if (md->paramcount > 0) {
991                         /* allocate memory for params */
992
993                         md->params = MNEW(paramdesc, md->paramcount);
994                 }
995                 else {
996                         md->params = METHODDESC_NOPARAMS;
997                 }
998
999                 /* fill the paramdesc */
1000                 /* md_param_alloc has to be called if md->paramcount == 0,
1001                    too, so it can make the reservation for the Linkage Area,
1002                    Return Register... */
1003
1004 #if defined(ENABLE_JIT)
1005 # if defined(ENABLE_INTRP)
1006                 if (!opt_intrp)
1007 # endif
1008                         {
1009                                 /* As builtin-functions are native functions, we have
1010                                    to pre-allocate for the native ABI. */
1011
1012                                 if (mflags & ACC_METHOD_BUILTIN)
1013                                         md_param_alloc_native(md);
1014                                 else
1015                                         md_param_alloc(md);
1016                         }
1017 #endif
1018
1019                 /* params already initialized; no need to lock */
1020                 md->pool_lock = NULL;
1021         }
1022         else {
1023                 /* params will be allocated later by
1024                    descriptor_params_from_paramtypes if necessary */
1025
1026                 md->params = NULL;
1027         }
1028
1029         *(pool->descriptor_kind_next++) = 'm';
1030
1031         d->parseddesc.md = md;
1032
1033         return md;
1034 }
1035
1036 /* descriptor_params_from_paramtypes *******************************************
1037  
1038    Create the paramdescs for a method descriptor. This function is
1039    called when we know whether the method is static or not. This
1040    function does nothing if md->params != NULL (checked atomically).
1041
1042    IN:
1043        md...............the parsed method descriptor
1044            mflags...........the ACC_* access flags of the method. Only the
1045                             ACC_STATIC bit is checked.
1046                                                 The value ACC_UNDEF is NOT allowed.
1047
1048    POSTCONDITION:
1049        md->parms != NULL
1050
1051 *******************************************************************************/
1052
1053 void descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1054 {
1055         bool has_lock = md->pool_lock;
1056
1057         assert(md);
1058         if (md->pool_lock)
1059                 md->pool_lock->lock();
1060         if (md->params) {
1061                 if (has_lock)
1062                         md->pool_lock->unlock();
1063                 return;
1064         }
1065         assert(md->params == NULL);
1066         assert(mflags != ACC_UNDEF);
1067
1068         typedesc *td = md->paramtypes;
1069
1070         /* check for `this' pointer */
1071
1072         if (!(mflags & ACC_STATIC)) {
1073                 constant_classref *thisclass;
1074
1075                 /* fetch class reference from reserved param slot */
1076                 thisclass = td[md->paramcount].classref;
1077                 assert(thisclass);
1078
1079                 if (md->paramcount > 0) {
1080                         /* shift param types by 1 argument */
1081                         MMOVE(td + 1, td, typedesc, md->paramcount);
1082                 }
1083
1084                 /* fill in first argument `this' */
1085
1086                 td->type = TYPE_ADR;
1087                 td->primitivetype = TYPE_ADR;
1088                 td->arraydim = 0;
1089                 td->classref = thisclass;
1090
1091                 md->paramcount++;
1092                 md->paramslots++;
1093         }
1094
1095         /* if the method has params, process them */
1096
1097         if (md->paramcount > 0) {
1098                 /* allocate memory for params */
1099
1100                 md->params = MNEW(paramdesc, md->paramcount);
1101
1102         } else {
1103                 md->params = METHODDESC_NOPARAMS;
1104         }
1105
1106         /* fill the paramdesc */
1107         /* md_param_alloc has to be called if md->paramcount == 0, too, so
1108            it can make the reservation for the Linkage Area, Return
1109            Register.. */
1110
1111 #if defined(ENABLE_JIT)
1112 # if defined(ENABLE_INTRP)
1113         if (!opt_intrp)
1114 # endif
1115                 {
1116                         /* As builtin-functions are native functions, we have to
1117                            pre-allocate for the native ABI. */
1118
1119                         if (mflags & ACC_METHOD_BUILTIN)
1120                                 md_param_alloc_native(md);
1121                         else
1122                                 md_param_alloc(md);
1123                 }
1124 #endif
1125
1126         if (has_lock)
1127                 md->pool_lock->unlock();
1128 }
1129
1130
1131 /* descriptor_pool_get_sizes ***************************************************
1132  
1133    Get the sizes of the class reference table and the parsed descriptors
1134
1135    IN:
1136        pool.............the descriptor_pool
1137
1138    OUT:
1139        *classrefsize....set to size of the class reference table
1140            *descsize........set to size of the parsed descriptors
1141
1142    NOTE:
1143        This function may only be called after both
1144                descriptor_pool_create_classrefs, and
1145                    descriptor_pool_alloc_parsed_descriptors
1146            have been called.
1147
1148 *******************************************************************************/
1149
1150 void 
1151 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1152 {
1153         assert(pool);
1154         assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1155         assert(pool->classrefs);
1156         assert(classrefsize);
1157         assert(descsize);
1158
1159         *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1160         *descsize = pool->descriptorsize;
1161 }
1162
1163
1164 /****************************************************************************/
1165 /* DEBUG HELPERS                                                            */
1166 /****************************************************************************/
1167
1168 #ifndef NDEBUG
1169 /* descriptor_debug_print_typedesc *********************************************
1170  
1171    Print the given typedesc to the given stream
1172
1173    IN:
1174            file.............stream to print to
1175            d................the parsed descriptor
1176
1177 *******************************************************************************/
1178
1179 void 
1180 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1181 {
1182         int ch;
1183
1184         if (!d) {
1185                 fprintf(file,"(typedesc *)NULL");
1186                 return;
1187         }
1188         
1189         if (d->type == TYPE_ADR) {
1190                 if (d->classref)
1191                         utf_fprint_printable_ascii(file,d->classref->name);
1192                 else
1193                         fprintf(file,"<class=NULL>");
1194         }
1195         else {
1196                 switch (d->primitivetype) {
1197                         case PRIMITIVETYPE_INT    : ch='I'; break;
1198                         case PRIMITIVETYPE_CHAR   : ch='C'; break;
1199                         case PRIMITIVETYPE_BYTE   : ch='B'; break;
1200                         case PRIMITIVETYPE_SHORT  : ch='S'; break;
1201                         case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1202                         case PRIMITIVETYPE_LONG   : ch='J'; break;
1203                         case PRIMITIVETYPE_FLOAT  : ch='F'; break;
1204                         case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1205                         case PRIMITIVETYPE_VOID   : ch='V'; break;
1206                         default                   : ch='!';
1207                 }
1208                 fputc(ch,file);
1209         }
1210         if (d->arraydim)
1211                 fprintf(file,"[%d]",d->arraydim);
1212 }
1213
1214 /* descriptor_debug_print_paramdesc ********************************************
1215  
1216    Print the given paramdesc to the given stream
1217
1218    IN:
1219            file.............stream to print to
1220            d................the parameter descriptor
1221
1222 *******************************************************************************/
1223
1224 void
1225 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1226 {
1227         if (!d) {
1228                 fprintf(file,"(paramdesc *)NULL");
1229                 return;
1230         }
1231         
1232         if (d->inmemory) {
1233                 fprintf(file,"<m%d>",d->regoff);
1234         }
1235         else {
1236                 fprintf(file,"<r%d>",d->regoff);
1237         }
1238 }
1239
1240 /* descriptor_debug_print_methoddesc *******************************************
1241  
1242    Print the given methoddesc to the given stream
1243
1244    IN:
1245            file.............stream to print to
1246            d................the parsed descriptor
1247
1248 *******************************************************************************/
1249
1250 void 
1251 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1252 {
1253         int i;
1254         
1255         if (!d) {
1256                 fprintf(file,"(methoddesc *)NULL");
1257                 return;
1258         }
1259         
1260         fputc('(',file);
1261         for (i=0; i<d->paramcount; ++i) {
1262                 if (i)
1263                         fputc(',',file);
1264                 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1265                 if (d->params) {
1266                         descriptor_debug_print_paramdesc(file,d->params + i);
1267                 }
1268         }
1269         if (d->params == METHODDESC_NOPARAMS)
1270                 fputs("<NOPARAMS>",file);
1271         fputc(')',file);
1272         descriptor_debug_print_typedesc(file,&(d->returntype));
1273 }
1274
1275 /* descriptor_pool_debug_dump **************************************************
1276  
1277    Print the state of the descriptor_pool to the given stream
1278
1279    IN:
1280        pool.............the descriptor_pool
1281            file.............stream to print to
1282
1283 *******************************************************************************/
1284
1285 void 
1286 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1287 {
1288         u4 slot;
1289         u1 *pos;
1290         u1 *kind;
1291         u4 size;
1292         
1293         fprintf(file,"======[descriptor_pool for ");
1294         utf_fprint_printable_ascii(file,pool->referer->name);
1295         fprintf(file,"]======\n");
1296
1297         fprintf(file,"fieldcount:     %d\n",pool->fieldcount);
1298         fprintf(file,"methodcount:    %d\n",pool->methodcount);
1299         fprintf(file,"paramcount:     %d\n",pool->paramcount);
1300         fprintf(file,"classrefcount:  %d\n",pool->classrefhash.entries);
1301         fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1302         fprintf(file,"classrefsize:   %d bytes\n",
1303                         (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1304
1305         fprintf(file,"class references:\n");
1306         for (slot=0; slot<pool->classrefhash.size; ++slot) {
1307                 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1308                 while (c) {
1309                         fprintf(file,"    %4d: ",c->index);
1310                         utf_fprint_printable_ascii(file,c->name);
1311                         fprintf(file,"\n");
1312                         c = c->hashlink;
1313                 }
1314         }
1315
1316         fprintf(file,"hashed descriptors:\n");
1317         for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1318                 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1319                 while (c) {
1320                         fprintf(file,"    %p: ",c->parseddesc.any);
1321                         utf_fprint_printable_ascii(file,c->desc);
1322                         fprintf(file,"\n");
1323                         c = c->hashlink;
1324                 }
1325         }
1326
1327         fprintf(file,"descriptors:\n");
1328         if (pool->descriptors) {
1329                 pos = pool->descriptors;
1330                 size = pool->descriptors_next - pool->descriptors;
1331                 fprintf(file,"    size: %d bytes\n",size);
1332                 
1333                 if (pool->descriptor_kind) {
1334                         kind = pool->descriptor_kind;
1335
1336                         while (pos < (pool->descriptors + size)) {
1337                                 fprintf(file,"    %p: ",pos);
1338                                 switch (*kind++) {
1339                                         case 'f':
1340                                                 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1341                                                 pos += sizeof(typedesc);
1342                                                 break;
1343                                         case 'm':
1344                                                 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1345                                                 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1346                                                 pos += sizeof(methoddesc) - sizeof(typedesc);
1347                                                 break;
1348                                         default:
1349                                                 fprintf(file,"INVALID KIND");
1350                                 }
1351                                 fputc('\n',file);
1352                         }
1353                 }
1354                 else {
1355                         while (size >= sizeof(void*)) {
1356                                 fprintf(file,"    %p\n",*((void**)pos));
1357                                 pos += sizeof(void*);
1358                                 size -= sizeof(void*);
1359                         }
1360                 }
1361         }
1362
1363         fprintf(file,"==========================================================\n");
1364 }
1365 #endif /* !defined(NDEBUG) */
1366
1367 #if defined(__cplusplus)
1368 }
1369 #endif
1370
1371 /*
1372  * These are local overrides for various environment variables in Emacs.
1373  * Please do not remove this and leave it at the end of the file, where
1374  * Emacs will automagically detect them.
1375  * ---------------------------------------------------------------------
1376  * Local variables:
1377  * mode: c
1378  * indent-tabs-mode: t
1379  * c-basic-offset: 4
1380  * tab-width: 4
1381  * End:
1382  * vim:noexpandtab:sw=4:ts=4:
1383  */
1384