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