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