* src/vm/jit/allocator/simplereg.c: Replaced HAS_4BYTE_STACKSLOT with
[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 8210 2007-07-18 12:51:00Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "md-abi.h"
37
38 #include "mm/memory.h"
39
40 #include "vm/exceptions.h"
41
42 #include "vm/jit_interface.h"
43
44 #include "vmcore/descriptor.h"
45 #include "vmcore/primitive.h"
46 #include "vmcore/options.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_DBL;
159                 case 'F':  return TYPE_FLT;
160                 case 'J':  return TYPE_LNG;
161                 case 'L':
162                 case '[':  return TYPE_ADR;
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_LNG: return 8;
189                 case TYPE_FLT: return 4;
190                 case TYPE_DBL: return 8;
191                 case TYPE_ADR: 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         exceptions_throw_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_ADR;
323                 td->decltype = TYPE_ADR;
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_DBL;
355                         break;
356                 case 'F':
357                         td->decltype = PRIMITIVETYPE_FLOAT;
358                         td->type = TYPE_FLT;
359                         break;
360                 case 'J':
361                         td->decltype = PRIMITIVETYPE_LONG;
362                         td->type = TYPE_LNG;
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_printable_ascii(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                 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
475                 return false; /* exception */
476         }
477
478         /* XXX check maximum array dimension */
479         
480         c = DNEW(classref_hash_entry);
481         c->name = name;
482         c->index = pool->classrefhash.entries++;
483         c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
484         pool->classrefhash.ptr[slot] = c;
485
486         return true;
487 }
488
489
490 /* descriptor_pool_add *********************************************************
491  
492    Check the given descriptor and add it to the pool
493
494    IN:
495        pool.............the descriptor_pool
496            desc.............the descriptor to add. Maybe a field or method desc.
497
498    OUT:
499        *paramslots......if non-NULL, set to the number of parameters.
500                             LONG and DOUBLE are counted twice
501
502    RETURN VALUE:
503        true.............descriptor has been added
504            false............an exception has been thrown
505
506 *******************************************************************************/
507
508 bool 
509 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
510 {
511         u4 key,slot;
512         descriptor_hash_entry *d;
513         char *utf_ptr;
514         char *end_pos;
515         utf *name;
516         s4 argcount = 0;
517         
518 #ifdef DESCRIPTOR_VERBOSE
519         fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
520         utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
521 #endif
522
523         assert(pool);
524         assert(desc);
525
526         /* find a place in the hashtable */
527
528         key = utf_hashkey(desc->text, desc->blength);
529         slot = key & (pool->descriptorhash.size - 1);
530         d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
531
532         /* Save all method descriptors in the hashtable, since the parsed         */
533         /* descriptor may vary between differenf methods (static vs. non-static). */
534
535         utf_ptr = desc->text;
536
537         if (*utf_ptr != '(') {
538                 while (d) {
539                         if (d->desc == desc) {
540                                 if (paramslots)
541                                         *paramslots = d->paramslots;
542                                 return true; /* already stored */
543                         }
544                         d = d->hashlink;
545                 }
546         }
547
548         /* add the descriptor to the pool */
549
550         d = DNEW(descriptor_hash_entry);
551         d->desc = desc;
552         d->parseddesc.any = NULL;
553         d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
554         pool->descriptorhash.ptr[slot] = d;
555
556         /* now check the descriptor */
557
558         end_pos = UTF_END(desc);
559         
560         if (*utf_ptr == '(') {
561                 /* a method descriptor */
562
563                 pool->methodcount++;
564                 utf_ptr++;
565
566                 /* check arguments */
567
568                 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
569                         pool->paramcount++;
570
571                         /* We cannot count the `this' argument here because
572                          * we don't know if the method is static. */
573
574                         if (*utf_ptr == 'J' || *utf_ptr == 'D')
575                                 argcount += 2;
576                         else
577                                 argcount++;
578
579                         if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
580                                                                       DESCRIPTOR_NOVOID, &name))
581                                 return false;
582
583                         if (name)
584                                 if (!descriptor_pool_add_class(pool, name))
585                                         return false;
586                 }
587
588                 if (utf_ptr == end_pos) {
589                         exceptions_throw_classformaterror(pool->referer,
590                                                                                           "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                         exceptions_throw_classformaterror(pool->referer,
606                                                                                           "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         exceptions_throw_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                 exceptions_throw_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_printable_ascii(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                 exceptions_throw_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 (IS_2_WORD_TYPE(td->type))
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 mflags != ACC_UNDEF we parse a real loaded method, so do
959            param prealloc.  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,
973                    too, so it can make the reservation for the Linkage Area,
974                    Return Register... */
975
976 #if defined(ENABLE_JIT)
977 # if defined(ENABLE_INTRP)
978                 if (!opt_intrp)
979 # endif
980                         {
981                                 /* As builtin-functions are native functions, we have
982                                    to pre-allocate for the native ABI. */
983
984                                 if (mflags & ACC_METHOD_BUILTIN)
985                                         md_param_alloc_native(md);
986                                 else
987                                         md_param_alloc(md);
988                         }
989 #endif
990         }
991         else {
992                 /* params will be allocated later by
993                    descriptor_params_from_paramtypes if necessary */
994
995                 md->params = NULL;
996         }
997
998         *(pool->descriptor_kind_next++) = 'm';
999
1000         d->parseddesc.md = md;
1001
1002         return md;
1003 }
1004
1005 /* descriptor_params_from_paramtypes *******************************************
1006  
1007    Create the paramdescs for a method descriptor. This function is called
1008    when we know whether the method is static or not. This function may only
1009    be called once for each methoddesc, and only if md->params == NULL.
1010
1011    IN:
1012        md...............the parsed method descriptor
1013                             md->params MUST be NULL.
1014            mflags...........the ACC_* access flags of the method. Only the
1015                             ACC_STATIC bit is checked.
1016                                                 The value ACC_UNDEF is NOT allowed.
1017
1018    RETURN VALUE:
1019        true.............the paramdescs were created successfully
1020            false............an exception has been thrown
1021
1022    POSTCONDITION:
1023        md->parms != NULL
1024
1025 *******************************************************************************/
1026
1027 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1028 {
1029         typedesc *td;
1030
1031         assert(md);
1032         assert(md->params == NULL);
1033         assert(mflags != ACC_UNDEF);
1034
1035         td = md->paramtypes;
1036
1037         /* check for `this' pointer */
1038
1039         if (!(mflags & ACC_STATIC)) {
1040                 constant_classref *thisclass;
1041
1042                 /* fetch class reference from reserved param slot */
1043                 thisclass = td[md->paramcount].classref;
1044                 assert(thisclass);
1045
1046                 if (md->paramcount > 0) {
1047                         /* shift param types by 1 argument */
1048                         MMOVE(td + 1, td, typedesc, md->paramcount);
1049                 }
1050
1051                 /* fill in first argument `this' */
1052
1053                 td->type = TYPE_ADR;
1054                 td->decltype = TYPE_ADR;
1055                 td->arraydim = 0;
1056                 td->classref = thisclass;
1057
1058                 md->paramcount++;
1059                 md->paramslots++;
1060         }
1061
1062         /* if the method has params, process them */
1063
1064         if (md->paramcount > 0) {
1065                 /* allocate memory for params */
1066
1067                 md->params = MNEW(paramdesc, md->paramcount);
1068
1069         } else {
1070                 md->params = METHODDESC_NOPARAMS;
1071         }
1072
1073         /* fill the paramdesc */
1074         /* md_param_alloc has to be called if md->paramcount == 0, too, so
1075            it can make the reservation for the Linkage Area, Return
1076            Register.. */
1077
1078 #if defined(ENABLE_JIT)
1079 # if defined(ENABLE_INTRP)
1080         if (!opt_intrp)
1081 # endif
1082                 {
1083                         /* As builtin-functions are native functions, we have to
1084                            pre-allocate for the native ABI. */
1085
1086                         if (mflags & ACC_METHOD_BUILTIN)
1087                                 md_param_alloc_native(md);
1088                         else
1089                                 md_param_alloc(md);
1090                 }
1091 #endif
1092
1093         return true;
1094 }
1095
1096
1097 /* descriptor_pool_get_parsed_descriptors **************************************
1098  
1099    Return a pointer to the block of parsed descriptors
1100
1101    IN:
1102        pool.............the descriptor_pool
1103
1104    OUT:
1105            *size............if size is non-NULL, this is set to the size of the
1106                             parsed descriptor block (in u1)
1107
1108    RETURN VALUE:
1109        a pointer to the block of parsed descriptors
1110
1111    NOTE:
1112        descriptor_pool_alloc_parsed_descriptors must be called (once)
1113        before this function is used.
1114
1115 *******************************************************************************/
1116
1117 void * 
1118 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1119 {
1120         assert(pool);
1121         assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1122         
1123         if (size)
1124                 *size = pool->descriptorsize;
1125
1126         return pool->descriptors;
1127 }
1128
1129
1130 /* descriptor_pool_get_sizes ***************************************************
1131  
1132    Get the sizes of the class reference table and the parsed descriptors
1133
1134    IN:
1135        pool.............the descriptor_pool
1136
1137    OUT:
1138        *classrefsize....set to size of the class reference table
1139            *descsize........set to size of the parsed descriptors
1140
1141    NOTE:
1142        This function may only be called after both
1143                descriptor_pool_create_classrefs, and
1144                    descriptor_pool_alloc_parsed_descriptors
1145            have been called.
1146
1147 *******************************************************************************/
1148
1149 void 
1150 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1151 {
1152         assert(pool);
1153         assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1154         assert(pool->classrefs);
1155         assert(classrefsize);
1156         assert(descsize);
1157
1158         *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1159         *descsize = pool->descriptorsize;
1160 }
1161
1162
1163 /****************************************************************************/
1164 /* DEBUG HELPERS                                                            */
1165 /****************************************************************************/
1166
1167 #ifndef NDEBUG
1168 /* descriptor_debug_print_typedesc *********************************************
1169  
1170    Print the given typedesc to the given stream
1171
1172    IN:
1173            file.............stream to print to
1174            d................the parsed descriptor
1175
1176 *******************************************************************************/
1177
1178 void 
1179 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1180 {
1181         int ch;
1182
1183         if (!d) {
1184                 fprintf(file,"(typedesc *)NULL");
1185                 return;
1186         }
1187         
1188         if (d->type == TYPE_ADR) {
1189                 if (d->classref)
1190                         utf_fprint_printable_ascii(file,d->classref->name);
1191                 else
1192                         fprintf(file,"<class=NULL>");
1193         }
1194         else {
1195                 switch (d->decltype) {
1196                         case PRIMITIVETYPE_INT    : ch='I'; break;
1197                         case PRIMITIVETYPE_CHAR   : ch='C'; break;
1198                         case PRIMITIVETYPE_BYTE   : ch='B'; break;
1199                         case PRIMITIVETYPE_SHORT  : ch='S'; break;
1200                         case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1201                         case PRIMITIVETYPE_LONG   : ch='J'; break;
1202                         case PRIMITIVETYPE_FLOAT  : ch='F'; break;
1203                         case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1204                         case PRIMITIVETYPE_VOID   : ch='V'; break;
1205                         default                   : ch='!';
1206                 }
1207                 fputc(ch,file);
1208         }
1209         if (d->arraydim)
1210                 fprintf(file,"[%d]",d->arraydim);
1211 }
1212
1213 /* descriptor_debug_print_paramdesc ********************************************
1214  
1215    Print the given paramdesc to the given stream
1216
1217    IN:
1218            file.............stream to print to
1219            d................the parameter descriptor
1220
1221 *******************************************************************************/
1222
1223 void
1224 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1225 {
1226         if (!d) {
1227                 fprintf(file,"(paramdesc *)NULL");
1228                 return;
1229         }
1230         
1231         if (d->inmemory) {
1232                 fprintf(file,"<m%d>",d->regoff);
1233         }
1234         else {
1235                 fprintf(file,"<r%d>",d->regoff);
1236         }
1237 }
1238
1239 /* descriptor_debug_print_methoddesc *******************************************
1240  
1241    Print the given methoddesc to the given stream
1242
1243    IN:
1244            file.............stream to print to
1245            d................the parsed descriptor
1246
1247 *******************************************************************************/
1248
1249 void 
1250 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1251 {
1252         int i;
1253         
1254         if (!d) {
1255                 fprintf(file,"(methoddesc *)NULL");
1256                 return;
1257         }
1258         
1259         fputc('(',file);
1260         for (i=0; i<d->paramcount; ++i) {
1261                 if (i)
1262                         fputc(',',file);
1263                 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1264                 if (d->params) {
1265                         descriptor_debug_print_paramdesc(file,d->params + i);
1266                 }
1267         }
1268         if (d->params == METHODDESC_NOPARAMS)
1269                 fputs("<NOPARAMS>",file);
1270         fputc(')',file);
1271         descriptor_debug_print_typedesc(file,&(d->returntype));
1272 }
1273
1274 /* descriptor_pool_debug_dump **************************************************
1275  
1276    Print the state of the descriptor_pool to the given stream
1277
1278    IN:
1279        pool.............the descriptor_pool
1280            file.............stream to print to
1281
1282 *******************************************************************************/
1283
1284 void 
1285 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1286 {
1287         u4 slot;
1288         u1 *pos;
1289         u1 *kind;
1290         u4 size;
1291         
1292         fprintf(file,"======[descriptor_pool for ");
1293         utf_fprint_printable_ascii(file,pool->referer->name);
1294         fprintf(file,"]======\n");
1295
1296         fprintf(file,"fieldcount:     %d\n",pool->fieldcount);
1297         fprintf(file,"methodcount:    %d\n",pool->methodcount);
1298         fprintf(file,"paramcount:     %d\n",pool->paramcount);
1299         fprintf(file,"classrefcount:  %d\n",pool->classrefhash.entries);
1300         fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1301         fprintf(file,"classrefsize:   %d bytes\n",
1302                         (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1303
1304         fprintf(file,"class references:\n");
1305         for (slot=0; slot<pool->classrefhash.size; ++slot) {
1306                 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1307                 while (c) {
1308                         fprintf(file,"    %4d: ",c->index);
1309                         utf_fprint_printable_ascii(file,c->name);
1310                         fprintf(file,"\n");
1311                         c = c->hashlink;
1312                 }
1313         }
1314
1315         fprintf(file,"hashed descriptors:\n");
1316         for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1317                 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1318                 while (c) {
1319                         fprintf(file,"    %p: ",c->parseddesc.any);
1320                         utf_fprint_printable_ascii(file,c->desc);
1321                         fprintf(file,"\n");
1322                         c = c->hashlink;
1323                 }
1324         }
1325
1326         fprintf(file,"descriptors:\n");
1327         if (pool->descriptors) {
1328                 pos = pool->descriptors;
1329                 size = pool->descriptors_next - pool->descriptors;
1330                 fprintf(file,"    size: %d bytes\n",size);
1331                 
1332                 if (pool->descriptor_kind) {
1333                         kind = pool->descriptor_kind;
1334
1335                         while (pos < (pool->descriptors + size)) {
1336                                 fprintf(file,"    %p: ",pos);
1337                                 switch (*kind++) {
1338                                         case 'f':
1339                                                 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1340                                                 pos += sizeof(typedesc);
1341                                                 break;
1342                                         case 'm':
1343                                                 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1344                                                 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1345                                                 pos += sizeof(methoddesc) - sizeof(typedesc);
1346                                                 break;
1347                                         default:
1348                                                 fprintf(file,"INVALID KIND");
1349                                 }
1350                                 fputc('\n',file);
1351                         }
1352                 }
1353                 else {
1354                         while (size >= sizeof(voidptr)) {
1355                                 fprintf(file,"    %p\n",*((voidptr*)pos));
1356                                 pos += sizeof(voidptr);
1357                                 size -= sizeof(voidptr);
1358                         }
1359                 }
1360         }
1361
1362         fprintf(file,"==========================================================\n");
1363 }
1364 #endif /* !defined(NDEBUG) */
1365
1366 /*
1367  * These are local overrides for various environment variables in Emacs.
1368  * Please do not remove this and leave it at the end of the file, where
1369  * Emacs will automagically detect them.
1370  * ---------------------------------------------------------------------
1371  * Local variables:
1372  * mode: c
1373  * indent-tabs-mode: t
1374  * c-basic-offset: 4
1375  * tab-width: 4
1376  * End:
1377  * vim:noexpandtab:sw=4:ts=4:
1378  */
1379