* src/vm/jit/intrp/peephole.c: Updated to current codebase.
[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 7356 2007-02-14 11:00:28Z 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/abi.h"
43
44 #include "vmcore/descriptor.h"
45 #include "vmcore/options.h"
46 #include "vmcore/resolve.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 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,
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                         md_param_alloc(md);
981 #endif
982
983         } else {
984                 /* params will be allocated later by
985                    descriptor_params_from_paramtypes if necessary */
986
987                 md->params = NULL;
988         }
989
990         *(pool->descriptor_kind_next++) = 'm';
991
992         d->parseddesc.md = md;
993
994         return md;
995 }
996
997 /* descriptor_params_from_paramtypes *******************************************
998  
999    Create the paramdescs for a method descriptor. This function is called
1000    when we know whether the method is static or not. This function may only
1001    be called once for each methoddesc, and only if md->params == NULL.
1002
1003    IN:
1004        md...............the parsed method descriptor
1005                             md->params MUST be NULL.
1006            mflags...........the ACC_* access flags of the method. Only the
1007                             ACC_STATIC bit is checked.
1008                                                 The value ACC_UNDEF is NOT allowed.
1009
1010    RETURN VALUE:
1011        true.............the paramdescs were created successfully
1012            false............an exception has been thrown
1013
1014    POSTCONDITION:
1015        md->parms != NULL
1016
1017 *******************************************************************************/
1018
1019 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1020 {
1021         typedesc *td;
1022
1023         assert(md);
1024         assert(md->params == NULL);
1025         assert(mflags != ACC_UNDEF);
1026
1027         td = md->paramtypes;
1028
1029         /* check for `this' pointer */
1030
1031         if (!(mflags & ACC_STATIC)) {
1032                 constant_classref *thisclass;
1033
1034                 /* fetch class reference from reserved param slot */
1035                 thisclass = td[md->paramcount].classref;
1036                 assert(thisclass);
1037
1038                 if (md->paramcount > 0) {
1039                         /* shift param types by 1 argument */
1040                         MMOVE(td + 1, td, typedesc, md->paramcount);
1041                 }
1042
1043                 /* fill in first argument `this' */
1044
1045                 td->type = TYPE_ADR;
1046                 td->decltype = TYPE_ADR;
1047                 td->arraydim = 0;
1048                 td->classref = thisclass;
1049
1050                 md->paramcount++;
1051                 md->paramslots++;
1052         }
1053
1054         /* if the method has params, process them */
1055
1056         if (md->paramcount > 0) {
1057                 /* allocate memory for params */
1058
1059                 md->params = MNEW(paramdesc, md->paramcount);
1060
1061         } else {
1062                 md->params = METHODDESC_NOPARAMS;
1063         }
1064
1065         /* fill the paramdesc */
1066         /* md_param_alloc has to be called if md->paramcount == 0, too, so
1067            it can make the reservation for the Linkage Area, Return
1068            Register.. */
1069
1070 #if defined(ENABLE_JIT)
1071 # if defined(ENABLE_INTRP)
1072         if (!opt_intrp)
1073 # endif
1074                 md_param_alloc(md);
1075 #endif
1076
1077         return true;
1078 }
1079
1080
1081 /* descriptor_pool_get_parsed_descriptors **************************************
1082  
1083    Return a pointer to the block of parsed descriptors
1084
1085    IN:
1086        pool.............the descriptor_pool
1087
1088    OUT:
1089            *size............if size is non-NULL, this is set to the size of the
1090                             parsed descriptor block (in u1)
1091
1092    RETURN VALUE:
1093        a pointer to the block of parsed descriptors
1094
1095    NOTE:
1096        descriptor_pool_alloc_parsed_descriptors must be called (once)
1097        before this function is used.
1098
1099 *******************************************************************************/
1100
1101 void * 
1102 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1103 {
1104         assert(pool);
1105         assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1106         
1107         if (size)
1108                 *size = pool->descriptorsize;
1109
1110         return pool->descriptors;
1111 }
1112
1113
1114 /* descriptor_pool_get_sizes ***************************************************
1115  
1116    Get the sizes of the class reference table and the parsed descriptors
1117
1118    IN:
1119        pool.............the descriptor_pool
1120
1121    OUT:
1122        *classrefsize....set to size of the class reference table
1123            *descsize........set to size of the parsed descriptors
1124
1125    NOTE:
1126        This function may only be called after both
1127                descriptor_pool_create_classrefs, and
1128                    descriptor_pool_alloc_parsed_descriptors
1129            have been called.
1130
1131 *******************************************************************************/
1132
1133 void 
1134 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1135 {
1136         assert(pool);
1137         assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1138         assert(pool->classrefs);
1139         assert(classrefsize);
1140         assert(descsize);
1141
1142         *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1143         *descsize = pool->descriptorsize;
1144 }
1145
1146
1147 /****************************************************************************/
1148 /* DEBUG HELPERS                                                            */
1149 /****************************************************************************/
1150
1151 #ifndef NDEBUG
1152 /* descriptor_debug_print_typedesc *********************************************
1153  
1154    Print the given typedesc to the given stream
1155
1156    IN:
1157            file.............stream to print to
1158            d................the parsed descriptor
1159
1160 *******************************************************************************/
1161
1162 void 
1163 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1164 {
1165         int ch;
1166
1167         if (!d) {
1168                 fprintf(file,"(typedesc *)NULL");
1169                 return;
1170         }
1171         
1172         if (d->type == TYPE_ADR) {
1173                 if (d->classref)
1174                         utf_fprint_printable_ascii(file,d->classref->name);
1175                 else
1176                         fprintf(file,"<class=NULL>");
1177         }
1178         else {
1179                 switch (d->decltype) {
1180                         case PRIMITIVETYPE_INT    : ch='I'; break;
1181                         case PRIMITIVETYPE_CHAR   : ch='C'; break;
1182                         case PRIMITIVETYPE_BYTE   : ch='B'; break;
1183                         case PRIMITIVETYPE_SHORT  : ch='S'; break;
1184                         case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1185                         case PRIMITIVETYPE_LONG   : ch='J'; break;
1186                         case PRIMITIVETYPE_FLOAT  : ch='F'; break;
1187                         case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1188                         case PRIMITIVETYPE_VOID   : ch='V'; break;
1189                         default                   : ch='!';
1190                 }
1191                 fputc(ch,file);
1192         }
1193         if (d->arraydim)
1194                 fprintf(file,"[%d]",d->arraydim);
1195 }
1196
1197 /* descriptor_debug_print_paramdesc ********************************************
1198  
1199    Print the given paramdesc to the given stream
1200
1201    IN:
1202            file.............stream to print to
1203            d................the parameter descriptor
1204
1205 *******************************************************************************/
1206
1207 void
1208 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1209 {
1210         if (!d) {
1211                 fprintf(file,"(paramdesc *)NULL");
1212                 return;
1213         }
1214         
1215         if (d->inmemory) {
1216                 fprintf(file,"<m%d>",d->regoff);
1217         }
1218         else {
1219                 fprintf(file,"<r%d>",d->regoff);
1220         }
1221 }
1222
1223 /* descriptor_debug_print_methoddesc *******************************************
1224  
1225    Print the given methoddesc to the given stream
1226
1227    IN:
1228            file.............stream to print to
1229            d................the parsed descriptor
1230
1231 *******************************************************************************/
1232
1233 void 
1234 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1235 {
1236         int i;
1237         
1238         if (!d) {
1239                 fprintf(file,"(methoddesc *)NULL");
1240                 return;
1241         }
1242         
1243         fputc('(',file);
1244         for (i=0; i<d->paramcount; ++i) {
1245                 if (i)
1246                         fputc(',',file);
1247                 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1248                 if (d->params) {
1249                         descriptor_debug_print_paramdesc(file,d->params + i);
1250                 }
1251         }
1252         if (d->params == METHODDESC_NOPARAMS)
1253                 fputs("<NOPARAMS>",file);
1254         fputc(')',file);
1255         descriptor_debug_print_typedesc(file,&(d->returntype));
1256 }
1257
1258 /* descriptor_pool_debug_dump **************************************************
1259  
1260    Print the state of the descriptor_pool to the given stream
1261
1262    IN:
1263        pool.............the descriptor_pool
1264            file.............stream to print to
1265
1266 *******************************************************************************/
1267
1268 void 
1269 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1270 {
1271         u4 slot;
1272         u1 *pos;
1273         u1 *kind;
1274         u4 size;
1275         
1276         fprintf(file,"======[descriptor_pool for ");
1277         utf_fprint_printable_ascii(file,pool->referer->name);
1278         fprintf(file,"]======\n");
1279
1280         fprintf(file,"fieldcount:     %d\n",pool->fieldcount);
1281         fprintf(file,"methodcount:    %d\n",pool->methodcount);
1282         fprintf(file,"paramcount:     %d\n",pool->paramcount);
1283         fprintf(file,"classrefcount:  %d\n",pool->classrefhash.entries);
1284         fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1285         fprintf(file,"classrefsize:   %d bytes\n",
1286                         (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1287
1288         fprintf(file,"class references:\n");
1289         for (slot=0; slot<pool->classrefhash.size; ++slot) {
1290                 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1291                 while (c) {
1292                         fprintf(file,"    %4d: ",c->index);
1293                         utf_fprint_printable_ascii(file,c->name);
1294                         fprintf(file,"\n");
1295                         c = c->hashlink;
1296                 }
1297         }
1298
1299         fprintf(file,"hashed descriptors:\n");
1300         for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1301                 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1302                 while (c) {
1303                         fprintf(file,"    %p: ",c->parseddesc.any);
1304                         utf_fprint_printable_ascii(file,c->desc);
1305                         fprintf(file,"\n");
1306                         c = c->hashlink;
1307                 }
1308         }
1309
1310         fprintf(file,"descriptors:\n");
1311         if (pool->descriptors) {
1312                 pos = pool->descriptors;
1313                 size = pool->descriptors_next - pool->descriptors;
1314                 fprintf(file,"    size: %d bytes\n",size);
1315                 
1316                 if (pool->descriptor_kind) {
1317                         kind = pool->descriptor_kind;
1318
1319                         while (pos < (pool->descriptors + size)) {
1320                                 fprintf(file,"    %p: ",pos);
1321                                 switch (*kind++) {
1322                                         case 'f':
1323                                                 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1324                                                 pos += sizeof(typedesc);
1325                                                 break;
1326                                         case 'm':
1327                                                 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1328                                                 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1329                                                 pos += sizeof(methoddesc) - sizeof(typedesc);
1330                                                 break;
1331                                         default:
1332                                                 fprintf(file,"INVALID KIND");
1333                                 }
1334                                 fputc('\n',file);
1335                         }
1336                 }
1337                 else {
1338                         while (size >= sizeof(voidptr)) {
1339                                 fprintf(file,"    %p\n",*((voidptr*)pos));
1340                                 pos += sizeof(voidptr);
1341                                 size -= sizeof(voidptr);
1342                         }
1343                 }
1344         }
1345
1346         fprintf(file,"==========================================================\n");
1347 }
1348 #endif /* !defined(NDEBUG) */
1349
1350 /*
1351  * These are local overrides for various environment variables in Emacs.
1352  * Please do not remove this and leave it at the end of the file, where
1353  * Emacs will automagically detect them.
1354  * ---------------------------------------------------------------------
1355  * Local variables:
1356  * mode: c
1357  * indent-tabs-mode: t
1358  * c-basic-offset: 4
1359  * tab-width: 4
1360  * End:
1361  * vim:noexpandtab:sw=4:ts=4:
1362  */
1363