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