1 /* src/vm/descriptor.c - checking and parsing of field / method descriptors
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
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.
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.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Edwin Steiner
29 Changes: Christian Thalinger
32 $Id: descriptor.c 2833 2005-06-26 21:47:29Z christian $
42 #include "mm/memory.h"
43 #include "vm/descriptor.h"
44 #include "vm/exceptions.h"
45 #include "vm/resolve.h"
46 #include "vm/stringlocal.h"
49 /* constants (private to descriptor.c) ****************************************/
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
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
59 /* data structures (private to descriptor.c) **********************************/
61 typedef struct classref_hash_entry classref_hash_entry;
62 typedef struct descriptor_hash_entry descriptor_hash_entry;
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 */
71 /* entry struct for the descriptorhash of descriptor_pool */
72 struct descriptor_hash_entry {
73 descriptor_hash_entry *hashlink;
75 parseddesc parseddesc;
76 s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
80 /****************************************************************************/
81 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
82 /****************************************************************************/
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.
89 * CAUTION: This macro does not check for an unexpected end of the
90 * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
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)
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.
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!
107 * utf_ptr....points to first char after the descriptor
108 * errorflag..set to true if the string ended unexpectedly
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; \
115 if (*(utf_ptr)++=='L') { \
116 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
118 if ((utf_ptr)[-1] != ';') \
119 (errorflag) = true; }} while(0)
122 /****************************************************************************/
124 /****************************************************************************/
127 #define DESCRIPTOR_DEBUG
130 #ifdef DESCRIPTOR_DEBUG
131 #define DESCRIPTOR_ASSERT(cond) assert(cond)
133 #define DESCRIPTOR_ASSERT(cond)
136 /* name_from_descriptor ********************************************************
138 Return the class name indicated by the given descriptor
139 (Internally used helper function)
142 c................class containing the descriptor
143 utf_ptr..........first character of descriptor
144 end_ptr..........first character after the end of the string
145 mode.............a combination (binary or) of the following flags:
147 (Flags marked with * are the default settings.)
149 How to handle "V" descriptors:
151 * DESCRIPTOR_VOID.....handle it like other primitive types
152 DESCRIPTOR_NOVOID...treat it as an error
154 How to deal with extra characters after the end of the
157 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
158 DESCRIPTOR_CHECKEND.....treat them as an error
161 *next............if non-NULL, *next is set to the first character after
162 the descriptor. (Undefined if an error occurs.)
163 *name............set to the utf name of the class
166 true.............descriptor parsed successfully
167 false............an exception has been thrown
169 *******************************************************************************/
171 #define DESCRIPTOR_VOID 0 /* default */
172 #define DESCRIPTOR_NOVOID 0x0040
173 #define DESCRIPTOR_NOCHECKEND 0 /* default */
174 #define DESCRIPTOR_CHECKEND 0x1000
177 name_from_descriptor(classinfo *c,
178 char *utf_ptr, char *end_ptr,
179 char **next, int mode, utf **name)
181 char *start = utf_ptr;
184 DESCRIPTOR_ASSERT(c);
185 DESCRIPTOR_ASSERT(utf_ptr);
186 DESCRIPTOR_ASSERT(end_ptr);
187 DESCRIPTOR_ASSERT(name);
190 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
192 if (mode & DESCRIPTOR_CHECKEND)
193 error |= (utf_ptr != end_ptr);
196 if (next) *next = utf_ptr;
200 if (mode & DESCRIPTOR_NOVOID)
218 *name = utf_new(start, utf_ptr - start);
223 *exceptionptr = new_classformaterror(c,"invalid descriptor");
228 /* descriptor_to_typedesc ******************************************************
230 Parse the given type descriptor and fill a typedesc struct
231 (Internally used helper function)
234 pool.............the descriptor pool
235 utf_ptr..........points to first character of type descriptor
236 end_pos..........points after last character of the whole descriptor
239 *next............set to next character after type descriptor
240 *d...............filled with parsed information
243 true.............parsing succeeded
244 false............an exception has been thrown
246 *******************************************************************************/
249 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
250 char **next, typedesc *td)
254 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
258 /* a reference type */
259 td->type = TYPE_ADDRESS;
260 td->decltype = TYPE_ADDRESS;
262 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
264 td->classref = descriptor_pool_lookup_classref(pool, name);
267 /* a primitive type */
270 td->decltype = PRIMITIVETYPE_BYTE;
274 td->decltype = PRIMITIVETYPE_CHAR;
278 td->decltype = PRIMITIVETYPE_SHORT;
282 td->decltype = PRIMITIVETYPE_BOOLEAN;
286 td->decltype = PRIMITIVETYPE_INT;
290 td->decltype = PRIMITIVETYPE_DOUBLE;
291 td->type = TYPE_DOUBLE;
294 td->decltype = PRIMITIVETYPE_FLOAT;
295 td->type = TYPE_FLOAT;
298 td->decltype = PRIMITIVETYPE_LONG;
299 td->type = TYPE_LONG;
302 td->decltype = PRIMITIVETYPE_VOID;
303 td->type = TYPE_VOID;
306 DESCRIPTOR_ASSERT(false);
317 /* descriptor_pool_new *********************************************************
319 Allocate a new descriptor_pool
322 referer..........class for which to create the pool
325 a pointer to the new descriptor_pool
327 *******************************************************************************/
330 descriptor_pool_new(classinfo *referer)
332 descriptor_pool *pool;
336 pool = DNEW(descriptor_pool);
337 DESCRIPTOR_ASSERT(pool);
339 pool->referer = referer;
340 pool->fieldcount = 0;
341 pool->methodcount = 0;
342 pool->paramcount = 0;
343 pool->descriptorsize = 0;
344 pool->descriptors = NULL;
345 pool->descriptors_next = NULL;
346 pool->classrefs = NULL;
347 pool->descriptor_kind = NULL;
348 pool->descriptor_kind_next = NULL;
350 hashsize = CLASSREFHASH_INIT_SIZE;
351 pool->classrefhash.size = hashsize;
352 pool->classrefhash.entries = 0;
353 pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
354 for (slot=0; slot<hashsize; ++slot)
355 pool->classrefhash.ptr[slot] = NULL;
357 hashsize = DESCRIPTORHASH_INIT_SIZE;
358 pool->descriptorhash.size = hashsize;
359 pool->descriptorhash.entries = 0;
360 pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
361 for (slot=0; slot<hashsize; ++slot)
362 pool->descriptorhash.ptr[slot] = NULL;
368 /* descriptor_pool_add_class ***************************************************
370 Add the given class reference to the pool
373 pool.............the descriptor_pool
374 name.............the class reference to add
377 true.............reference has been added
378 false............an exception has been thrown
380 *******************************************************************************/
383 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
386 classref_hash_entry *c;
388 DESCRIPTOR_ASSERT(pool);
389 DESCRIPTOR_ASSERT(name);
391 /* find a place in the hashtable */
393 key = utf_hashkey(name->text, name->blength);
394 slot = key & (pool->classrefhash.size - 1);
395 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
399 return true; /* already stored */
403 /* check if the name is a valid classname */
405 if (!is_valid_name(name->text,UTF_END(name))) {
406 *exceptionptr = new_classformaterror(pool->referer,
407 "Invalid class name");
408 return false; /* exception */
411 /* XXX check maximum array dimension */
413 c = DNEW(classref_hash_entry);
415 c->index = pool->classrefhash.entries++;
416 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
417 pool->classrefhash.ptr[slot] = c;
423 /* descriptor_pool_add *********************************************************
425 Check the given descriptor and add it to the pool
428 pool.............the descriptor_pool
429 desc.............the descriptor to add. Maybe a field or method desc.
432 *paramslots......if non-NULL, set to the number of parameters.
433 LONG and DOUBLE are counted twice
436 true.............descriptor has been added
437 false............an exception has been thrown
439 *******************************************************************************/
442 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
445 descriptor_hash_entry *d;
451 DESCRIPTOR_ASSERT(pool);
452 DESCRIPTOR_ASSERT(desc);
454 /* find a place in the hashtable */
456 key = utf_hashkey(desc->text, desc->blength);
457 slot = key & (pool->descriptorhash.size - 1);
458 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
460 /* Save all method descriptors in the hashtable, since the parsed */
461 /* descriptor may vary between differenf methods (static vs. non-static). */
463 utf_ptr = desc->text;
465 if (*utf_ptr != '(') {
467 if (d->desc == desc) {
469 *paramslots = d->paramslots;
470 return true; /* already stored */
476 /* add the descriptor to the pool */
478 d = DNEW(descriptor_hash_entry);
480 d->parseddesc.any = NULL;
481 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
482 pool->descriptorhash.ptr[slot] = d;
484 /* now check the descriptor */
486 end_pos = UTF_END(desc);
488 if (*utf_ptr == '(') {
489 /* a method descriptor */
494 /* check arguments */
496 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
499 /* We cannot count the `this' argument here because
500 * we don't know if the method is static. */
502 if (*utf_ptr == 'J' || *utf_ptr == 'D')
507 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
508 DESCRIPTOR_NOVOID, &name))
512 descriptor_pool_add_class(pool, name);
515 if (utf_ptr == end_pos) {
516 *exceptionptr = new_classformaterror(pool->referer,"Missing ')' in method descriptor");
520 utf_ptr++; /* skip ')' */
522 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
523 DESCRIPTOR_CHECKEND, &name))
527 descriptor_pool_add_class(pool,name);
529 if (argcount > 255) {
531 new_classformaterror(pool->referer,"Too many arguments in signature");
536 /* a field descriptor */
539 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
540 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
545 descriptor_pool_add_class(pool,name);
548 d->paramslots = argcount;
551 *paramslots = argcount;
557 /* descriptor_pool_create_classrefs ********************************************
559 Create a table containing all the classrefs which were added to the pool
562 pool.............the descriptor_pool
565 *count...........if count is non-NULL, this is set to the number
566 of classrefs in the table
569 a pointer to the constant_classref table
571 *******************************************************************************/
574 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
578 classref_hash_entry *c;
579 constant_classref *ref;
581 DESCRIPTOR_ASSERT(pool);
583 nclasses = pool->classrefhash.entries;
584 pool->classrefs = MNEW(constant_classref,nclasses);
586 /* fill the constant_classref structs */
588 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
589 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
591 ref = pool->classrefs + c->index;
592 CLASSREF_INIT(*ref, pool->referer, c->name);
600 return pool->classrefs;
604 /* descriptor_pool_lookup_classref *********************************************
606 Return the constant_classref for the given class name
609 pool.............the descriptor_pool
610 classname........name of the class to look up
613 a pointer to the constant_classref, or
614 NULL if an exception has been thrown
616 *******************************************************************************/
619 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
622 classref_hash_entry *c;
624 DESCRIPTOR_ASSERT(pool);
625 DESCRIPTOR_ASSERT(pool->classrefs);
626 DESCRIPTOR_ASSERT(classname);
628 key = utf_hashkey(classname->text, classname->blength);
629 slot = key & (pool->classrefhash.size - 1);
630 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
633 if (c->name == classname)
634 return pool->classrefs + c->index;
639 new_exception_message(string_java_lang_InternalError,
640 "Class reference not found in descriptor pool");
645 /* descriptor_pool_alloc_parsed_descriptors ************************************
647 Allocate space for the parsed descriptors
650 pool.............the descriptor_pool
653 This function must be called after all descriptors have been added
654 with descriptor_pool_add.
656 *******************************************************************************/
659 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
663 DESCRIPTOR_ASSERT(pool);
665 /* TWISTI: paramcount + 1: we don't know if the method is static or */
666 /* not, i have no better solution yet. */
669 pool->fieldcount * sizeof(typedesc) +
670 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
671 pool->paramcount * sizeof(typedesc) +
672 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
674 pool->descriptorsize = size;
676 pool->descriptors = MNEW(u1, size);
677 pool->descriptors_next = pool->descriptors;
680 size = pool->fieldcount + pool->methodcount;
682 pool->descriptor_kind = DMNEW(u1, size);
683 pool->descriptor_kind_next = pool->descriptor_kind;
688 /* descriptor_pool_parse_field_descriptor **************************************
690 Parse the given field descriptor
693 pool.............the descriptor_pool
694 desc.............the field descriptor
697 a pointer to the parsed field descriptor, or
698 NULL if an exception has been thrown
701 descriptor_pool_alloc_parsed_descriptors must be called (once)
702 before this function is used.
704 *******************************************************************************/
707 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
710 descriptor_hash_entry *d;
713 DESCRIPTOR_ASSERT(pool);
714 DESCRIPTOR_ASSERT(pool->descriptors);
715 DESCRIPTOR_ASSERT(pool->descriptors_next);
717 /* lookup the descriptor in the hashtable */
719 key = utf_hashkey(desc->text, desc->blength);
720 slot = key & (pool->descriptorhash.size - 1);
721 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
724 if (d->desc == desc) {
726 if (d->parseddesc.fd)
727 return d->parseddesc.fd;
733 DESCRIPTOR_ASSERT(d);
735 if (desc->text[0] == '(') {
736 *exceptionptr = new_classformaterror(pool->referer,
737 "Method descriptor used in field reference");
741 td = (typedesc *) pool->descriptors_next;
742 pool->descriptors_next += sizeof(typedesc);
744 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
747 *(pool->descriptor_kind_next++) = 'f';
749 d->parseddesc.fd = td;
755 /* descriptor_pool_parse_method_descriptor *************************************
757 Parse the given method descriptor
760 pool.............the descriptor_pool
761 desc.............the method descriptor
762 mflags...........the method flags
763 thisclass........classref to the class containing the method.
764 This is ignored if mflags contains ACC_STATIC.
765 The classref is stored for inserting the 'this' argument.
768 a pointer to the parsed method descriptor, or
769 NULL if an exception has been thrown
772 descriptor_pool_alloc_parsed_descriptors must be called
773 (once) before this function is used.
775 *******************************************************************************/
778 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
779 s4 mflags,constant_classref *thisclass)
782 descriptor_hash_entry *d;
790 DESCRIPTOR_ASSERT(pool);
791 DESCRIPTOR_ASSERT(pool->descriptors);
792 DESCRIPTOR_ASSERT(pool->descriptors_next);
794 /* lookup the descriptor in the hashtable */
796 key = utf_hashkey(desc->text, desc->blength);
797 slot = key & (pool->descriptorhash.size - 1);
798 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
800 /* find an un-parsed descriptor */
804 if (!d->parseddesc.md)
809 DESCRIPTOR_ASSERT(d);
811 md = (methoddesc *) pool->descriptors_next;
812 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
814 utf_ptr = desc->text;
815 end_pos = UTF_END(desc);
817 if (*utf_ptr++ != '(') {
818 *exceptionptr = new_classformaterror(pool->referer,
819 "Field descriptor used in method reference");
825 /* count the `this' pointer */
827 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
829 td->decltype = TYPE_ADR;
831 td->classref = thisclass;
834 pool->descriptors_next += sizeof(typedesc);
839 while (*utf_ptr != ')') {
840 /* parse a parameter type */
842 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
845 if (td->type == TYPE_LONG || td->type == TYPE_DOUBLE)
849 pool->descriptors_next += sizeof(typedesc);
853 utf_ptr++; /* skip ')' */
855 /* Skip possible `this' pointer in paramtypes array to allow a possible */
856 /* memory move later in parse. */
857 /* We store the thisclass reference, so we can later correctly fill in */
858 /* the parameter slot of the 'this' argument. */
860 if (mflags == ACC_UNDEF) {
861 td->classref = thisclass;
863 pool->descriptors_next += sizeof(typedesc);
866 /* parse return type */
868 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
872 md->paramcount = paramcount;
873 md->paramslots = paramslots;
875 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
876 /* Otherwise we do this in stack analysis. */
878 if (mflags != ACC_UNDEF) {
879 if (md->paramcount > 0) {
880 /* allocate memory for params */
882 md->params = MNEW(paramdesc, md->paramcount);
885 md->params = METHODDESC_NOPARAMS;
888 /* fill the paramdesc */
889 /* md_param_alloc has to be called if md->paramcount == 0, too, so it */
890 /* can make the reservation for the Linkage Area, Return Register... */
894 /* params will be allocated later by descriptor_params_from_paramtypes */
899 *(pool->descriptor_kind_next++) = 'm';
901 d->parseddesc.md = md;
906 /* descriptor_params_from_paramtypes *******************************************
908 Create the paramdescs for a method descriptor. This function is called
909 when we know whether the method is static or not. This function may only
910 be called once for each methoddesc, and only if md->params == NULL.
913 md...............the parsed method descriptor
914 md->params MUST be NULL.
915 mflags...........the ACC_* access flags of the method. Only the
916 ACC_STATIC bit is checked.
917 The value ACC_UNDEF is NOT allowed.
920 true.............the paramdescs were created successfully
921 false............an exception has been thrown
926 *******************************************************************************/
928 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
932 DESCRIPTOR_ASSERT(md);
933 DESCRIPTOR_ASSERT(md->params == NULL);
934 DESCRIPTOR_ASSERT(mflags != ACC_UNDEF);
938 /* check for `this' pointer */
940 if (!(mflags & ACC_STATIC)) {
941 constant_classref *thisclass;
943 /* fetch class reference from reserved param slot */
944 thisclass = td[md->paramcount].classref;
945 DESCRIPTOR_ASSERT(thisclass);
947 if (md->paramcount > 0) {
948 /* shift param types by 1 argument */
949 MMOVE(td + 1, td, typedesc, md->paramcount);
952 /* fill in first argument `this' */
955 td->decltype = TYPE_ADR;
957 td->classref = thisclass;
963 /* if the method has params, process them */
965 if (md->paramcount > 0) {
966 /* allocate memory for params */
968 md->params = MNEW(paramdesc, md->paramcount);
971 md->params = METHODDESC_NOPARAMS;
974 /* fill the paramdesc */
975 /* md_param_alloc has to be called if md->paramcount == 0, too, so */
976 /* it can make the reservation for the Linkage Area, Return Register.. */
984 /* descriptor_pool_get_parsed_descriptors **************************************
986 Return a pointer to the block of parsed descriptors
989 pool.............the descriptor_pool
992 *size............if size is non-NULL, this is set to the size of the
993 parsed descriptor block (in u1)
996 a pointer to the block of parsed descriptors
999 descriptor_pool_alloc_parsed_descriptors must be called (once)
1000 before this function is used.
1002 *******************************************************************************/
1005 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1007 DESCRIPTOR_ASSERT(pool);
1008 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1011 *size = pool->descriptorsize;
1013 return pool->descriptors;
1017 /* descriptor_pool_get_sizes ***************************************************
1019 Get the sizes of the class reference table and the parsed descriptors
1022 pool.............the descriptor_pool
1025 *classrefsize....set to size of the class reference table
1026 *descsize........set to size of the parsed descriptors
1029 This function may only be called after both
1030 descriptor_pool_create_classrefs, and
1031 descriptor_pool_alloc_parsed_descriptors
1034 *******************************************************************************/
1037 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1039 DESCRIPTOR_ASSERT(pool);
1040 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1041 DESCRIPTOR_ASSERT(pool->classrefs);
1042 DESCRIPTOR_ASSERT(classrefsize);
1043 DESCRIPTOR_ASSERT(descsize);
1045 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1046 *descsize = pool->descriptorsize;
1050 /* descriptor_debug_print_typedesc *********************************************
1052 Print the given typedesc to the given stream
1055 file.............stream to print to
1056 d................the parsed descriptor
1058 *******************************************************************************/
1061 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1066 fprintf(file,"(typedesc *)NULL");
1070 if (d->type == TYPE_ADDRESS) {
1072 utf_fprint(file,d->classref->name);
1074 fprintf(file,"<class=NULL>");
1077 switch (d->decltype) {
1078 case PRIMITIVETYPE_INT : ch='I'; break;
1079 case PRIMITIVETYPE_CHAR : ch='C'; break;
1080 case PRIMITIVETYPE_BYTE : ch='B'; break;
1081 case PRIMITIVETYPE_SHORT : ch='S'; break;
1082 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1083 case PRIMITIVETYPE_LONG : ch='J'; break;
1084 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1085 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1086 case PRIMITIVETYPE_VOID : ch='V'; break;
1092 fprintf(file,"[%d]",d->arraydim);
1095 /* descriptor_debug_print_paramdesc ********************************************
1097 Print the given paramdesc to the given stream
1100 file.............stream to print to
1101 d................the parameter descriptor
1103 *******************************************************************************/
1106 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1109 fprintf(file,"(paramdesc *)NULL");
1114 fprintf(file,"<m%d>",d->regoff);
1117 fprintf(file,"<r%d>",d->regoff);
1121 /* descriptor_debug_print_methoddesc *******************************************
1123 Print the given methoddesc to the given stream
1126 file.............stream to print to
1127 d................the parsed descriptor
1129 *******************************************************************************/
1132 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1137 fprintf(file,"(methoddesc *)NULL");
1142 for (i=0; i<d->paramcount; ++i) {
1145 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1147 descriptor_debug_print_paramdesc(file,d->params + i);
1150 if (d->params == METHODDESC_NOPARAMS)
1151 fputs("<NOPARAMS>",file);
1153 descriptor_debug_print_typedesc(file,&(d->returntype));
1156 /* descriptor_pool_debug_dump **************************************************
1158 Print the state of the descriptor_pool to the given stream
1161 pool.............the descriptor_pool
1162 file.............stream to print to
1164 *******************************************************************************/
1167 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1174 fprintf(file,"======[descriptor_pool for ");
1175 utf_fprint(file,pool->referer->name);
1176 fprintf(file,"]======\n");
1178 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1179 fprintf(file,"methodcount: %d\n",pool->methodcount);
1180 fprintf(file,"paramcount: %d\n",pool->paramcount);
1181 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1182 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1183 fprintf(file,"classrefsize: %d bytes\n",
1184 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1186 fprintf(file,"class references:\n");
1187 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1188 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1190 fprintf(file," %4d: ",c->index);
1191 utf_fprint(file,c->name);
1197 fprintf(file,"hashed descriptors:\n");
1198 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1199 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1201 fprintf(file," %p: ",c->parseddesc.any);
1202 utf_fprint(file,c->desc);
1208 fprintf(file,"descriptors:\n");
1209 if (pool->descriptors) {
1210 pos = pool->descriptors;
1211 size = pool->descriptors_next - pool->descriptors;
1212 fprintf(file," size: %d bytes\n",size);
1214 if (pool->descriptor_kind) {
1215 kind = pool->descriptor_kind;
1217 while (pos < (pool->descriptors + size)) {
1218 fprintf(file," %p: ",pos);
1221 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1222 pos += sizeof(typedesc);
1225 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1226 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1227 pos += sizeof(methoddesc) - sizeof(typedesc);
1230 fprintf(file,"INVALID KIND");
1236 while (size >= sizeof(voidptr)) {
1237 fprintf(file," %p\n",*((voidptr*)pos));
1238 pos += sizeof(voidptr);
1239 size -= sizeof(voidptr);
1244 fprintf(file,"==========================================================\n");
1248 * These are local overrides for various environment variables in Emacs.
1249 * Please do not remove this and leave it at the end of the file, where
1250 * Emacs will automagically detect them.
1251 * ---------------------------------------------------------------------
1254 * indent-tabs-mode: t
1258 * vim:noexpandtab:sw=4:ts=4: