1 /* src/vmcore/descriptor.c - checking and parsing of field / method descriptors
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
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., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: descriptor.c 7356 2007-02-14 11:00:28Z twisti $
38 #include "mm/memory.h"
40 #include "vm/exceptions.h"
42 #include "vm/jit/abi.h"
44 #include "vmcore/descriptor.h"
45 #include "vmcore/options.h"
46 #include "vmcore/resolve.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 /****************************************************************************/
126 /*#define DESCRIPTOR_VERBOSE*/
128 /****************************************************************************/
130 /****************************************************************************/
132 /* descriptor_to_basic_type ****************************************************
134 Return the basic type to use for a value with this descriptor.
137 utf..............descriptor utf string
143 This function assumes that the descriptor has passed
144 descriptor_pool_add checks and that it does not start with '('.
146 *******************************************************************************/
148 u2 descriptor_to_basic_type(utf *descriptor)
150 assert(descriptor->blength >= 1);
152 switch (descriptor->text[0]) {
157 case 'Z': return TYPE_INT;
158 case 'D': return TYPE_DBL;
159 case 'F': return TYPE_FLT;
160 case 'J': return TYPE_LNG;
162 case '[': return TYPE_ADR;
167 return 0; /* keep the compiler happy */
170 /* descriptor_typesize**** ****************************************************
172 Return the size in bytes needed for the given type.
175 td..............typedesc describing the type
180 *******************************************************************************/
182 u2 descriptor_typesize(typedesc *td)
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);
196 return 0; /* keep the compiler happy */
199 /* name_from_descriptor ********************************************************
201 Return the class name indicated by the given descriptor
202 (Internally used helper function)
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:
210 (Flags marked with * are the default settings.)
212 How to handle "V" descriptors:
214 * DESCRIPTOR_VOID.....handle it like other primitive types
215 DESCRIPTOR_NOVOID...treat it as an error
217 How to deal with extra characters after the end of the
220 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
221 DESCRIPTOR_CHECKEND.....treat them as an error
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
229 true.............descriptor parsed successfully
230 false............an exception has been thrown
232 *******************************************************************************/
234 #define DESCRIPTOR_VOID 0 /* default */
235 #define DESCRIPTOR_NOVOID 0x0040
236 #define DESCRIPTOR_NOCHECKEND 0 /* default */
237 #define DESCRIPTOR_CHECKEND 0x1000
240 name_from_descriptor(classinfo *c,
241 char *utf_ptr, char *end_ptr,
242 char **next, int mode, utf **name)
244 char *start = utf_ptr;
253 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
255 if (mode & DESCRIPTOR_CHECKEND)
256 error |= (utf_ptr != end_ptr);
259 if (next) *next = utf_ptr;
263 if (mode & DESCRIPTOR_NOVOID)
281 *name = utf_new(start, utf_ptr - start);
286 exceptions_throw_classformaterror(c, "Invalid descriptor");
291 /* descriptor_to_typedesc ******************************************************
293 Parse the given type descriptor and fill a typedesc struct
294 (Internally used helper function)
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
302 *next............set to next character after type descriptor
303 *d...............filled with parsed information
306 true.............parsing succeeded
307 false............an exception has been thrown
309 *******************************************************************************/
312 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
313 char **next, typedesc *td)
317 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
321 /* a reference type */
323 td->decltype = TYPE_ADR;
325 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
327 td->classref = descriptor_pool_lookup_classref(pool, name);
330 /* a primitive type */
333 td->decltype = PRIMITIVETYPE_BYTE;
337 td->decltype = PRIMITIVETYPE_CHAR;
341 td->decltype = PRIMITIVETYPE_SHORT;
345 td->decltype = PRIMITIVETYPE_BOOLEAN;
349 td->decltype = PRIMITIVETYPE_INT;
353 td->decltype = PRIMITIVETYPE_DOUBLE;
357 td->decltype = PRIMITIVETYPE_FLOAT;
361 td->decltype = PRIMITIVETYPE_LONG;
365 td->decltype = PRIMITIVETYPE_VOID;
366 td->type = TYPE_VOID;
380 /* descriptor_pool_new *********************************************************
382 Allocate a new descriptor_pool
385 referer..........class for which to create the pool
388 a pointer to the new descriptor_pool
390 *******************************************************************************/
393 descriptor_pool_new(classinfo *referer)
395 descriptor_pool *pool;
399 pool = DNEW(descriptor_pool);
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;
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;
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;
431 /* descriptor_pool_add_class ***************************************************
433 Add the given class reference to the pool
436 pool.............the descriptor_pool
437 name.............the class reference to add
440 true.............reference has been added
441 false............an exception has been thrown
443 *******************************************************************************/
446 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
449 classref_hash_entry *c;
454 #ifdef DESCRIPTOR_VERBOSE
455 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
456 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
459 /* find a place in the hashtable */
461 key = utf_hashkey(name->text, name->blength);
462 slot = key & (pool->classrefhash.size - 1);
463 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
467 return true; /* already stored */
471 /* check if the name is a valid classname */
473 if (!is_valid_name(name->text,UTF_END(name))) {
474 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
475 return false; /* exception */
478 /* XXX check maximum array dimension */
480 c = DNEW(classref_hash_entry);
482 c->index = pool->classrefhash.entries++;
483 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
484 pool->classrefhash.ptr[slot] = c;
490 /* descriptor_pool_add *********************************************************
492 Check the given descriptor and add it to the pool
495 pool.............the descriptor_pool
496 desc.............the descriptor to add. Maybe a field or method desc.
499 *paramslots......if non-NULL, set to the number of parameters.
500 LONG and DOUBLE are counted twice
503 true.............descriptor has been added
504 false............an exception has been thrown
506 *******************************************************************************/
509 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
512 descriptor_hash_entry *d;
518 #ifdef DESCRIPTOR_VERBOSE
519 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
520 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
526 /* find a place in the hashtable */
528 key = utf_hashkey(desc->text, desc->blength);
529 slot = key & (pool->descriptorhash.size - 1);
530 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
532 /* Save all method descriptors in the hashtable, since the parsed */
533 /* descriptor may vary between differenf methods (static vs. non-static). */
535 utf_ptr = desc->text;
537 if (*utf_ptr != '(') {
539 if (d->desc == desc) {
541 *paramslots = d->paramslots;
542 return true; /* already stored */
548 /* add the descriptor to the pool */
550 d = DNEW(descriptor_hash_entry);
552 d->parseddesc.any = NULL;
553 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
554 pool->descriptorhash.ptr[slot] = d;
556 /* now check the descriptor */
558 end_pos = UTF_END(desc);
560 if (*utf_ptr == '(') {
561 /* a method descriptor */
566 /* check arguments */
568 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
571 /* We cannot count the `this' argument here because
572 * we don't know if the method is static. */
574 if (*utf_ptr == 'J' || *utf_ptr == 'D')
579 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
580 DESCRIPTOR_NOVOID, &name))
584 if (!descriptor_pool_add_class(pool, name))
588 if (utf_ptr == end_pos) {
589 exceptions_throw_classformaterror(pool->referer,
590 "Missing ')' in method descriptor");
594 utf_ptr++; /* skip ')' */
596 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
597 DESCRIPTOR_CHECKEND, &name))
601 if (!descriptor_pool_add_class(pool,name))
604 if (argcount > 255) {
605 exceptions_throw_classformaterror(pool->referer,
606 "Too many arguments in signature");
611 /* a field descriptor */
615 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
616 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
621 if (!descriptor_pool_add_class(pool,name))
625 d->paramslots = argcount;
628 *paramslots = argcount;
634 /* descriptor_pool_create_classrefs ********************************************
636 Create a table containing all the classrefs which were added to the pool
639 pool.............the descriptor_pool
642 *count...........if count is non-NULL, this is set to the number
643 of classrefs in the table
646 a pointer to the constant_classref table
648 *******************************************************************************/
651 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
655 classref_hash_entry *c;
656 constant_classref *ref;
660 nclasses = pool->classrefhash.entries;
661 pool->classrefs = MNEW(constant_classref,nclasses);
663 /* fill the constant_classref structs */
665 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
666 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
668 ref = pool->classrefs + c->index;
669 CLASSREF_INIT(*ref, pool->referer, c->name);
677 return pool->classrefs;
681 /* descriptor_pool_lookup_classref *********************************************
683 Return the constant_classref for the given class name
686 pool.............the descriptor_pool
687 classname........name of the class to look up
690 a pointer to the constant_classref, or
691 NULL if an exception has been thrown
693 *******************************************************************************/
696 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
699 classref_hash_entry *c;
702 assert(pool->classrefs);
705 key = utf_hashkey(classname->text, classname->blength);
706 slot = key & (pool->classrefhash.size - 1);
707 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
710 if (c->name == classname)
711 return pool->classrefs + c->index;
715 exceptions_throw_internalerror("Class reference not found in descriptor pool");
720 /* descriptor_pool_alloc_parsed_descriptors ************************************
722 Allocate space for the parsed descriptors
725 pool.............the descriptor_pool
728 This function must be called after all descriptors have been added
729 with descriptor_pool_add.
731 *******************************************************************************/
734 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
740 /* TWISTI: paramcount + 1: we don't know if the method is static or */
741 /* not, i have no better solution yet. */
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 */
749 pool->descriptorsize = size;
751 pool->descriptors = MNEW(u1, size);
752 pool->descriptors_next = pool->descriptors;
755 size = pool->fieldcount + pool->methodcount;
757 pool->descriptor_kind = DMNEW(u1, size);
758 pool->descriptor_kind_next = pool->descriptor_kind;
763 /* descriptor_pool_parse_field_descriptor **************************************
765 Parse the given field descriptor
768 pool.............the descriptor_pool
769 desc.............the field descriptor
772 a pointer to the parsed field descriptor, or
773 NULL if an exception has been thrown
776 descriptor_pool_alloc_parsed_descriptors must be called (once)
777 before this function is used.
779 *******************************************************************************/
782 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
785 descriptor_hash_entry *d;
789 assert(pool->descriptors);
790 assert(pool->descriptors_next);
792 /* lookup the descriptor in the hashtable */
794 key = utf_hashkey(desc->text, desc->blength);
795 slot = key & (pool->descriptorhash.size - 1);
796 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
799 if (d->desc == desc) {
801 if (d->parseddesc.fd)
802 return d->parseddesc.fd;
810 if (desc->text[0] == '(') {
811 exceptions_throw_classformaterror(pool->referer,
812 "Method descriptor used in field reference");
816 td = (typedesc *) pool->descriptors_next;
817 pool->descriptors_next += sizeof(typedesc);
819 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
822 *(pool->descriptor_kind_next++) = 'f';
824 d->parseddesc.fd = td;
830 /* descriptor_pool_parse_method_descriptor *************************************
832 Parse the given method descriptor
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.
843 a pointer to the parsed method descriptor, or
844 NULL if an exception has been thrown
847 descriptor_pool_alloc_parsed_descriptors must be called
848 (once) before this function is used.
850 *******************************************************************************/
853 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
854 s4 mflags,constant_classref *thisclass)
857 descriptor_hash_entry *d;
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");
872 assert(pool->descriptors);
873 assert(pool->descriptors_next);
875 /* check that it is a method descriptor */
877 if (desc->text[0] != '(') {
878 exceptions_throw_classformaterror(pool->referer,
879 "Field descriptor used in method reference");
883 /* lookup the descriptor in the hashtable */
885 key = utf_hashkey(desc->text, desc->blength);
886 slot = key & (pool->descriptorhash.size - 1);
887 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
889 /* find an un-parsed descriptor */
893 if (!d->parseddesc.md)
900 md = (methoddesc *) pool->descriptors_next;
901 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
903 utf_ptr = desc->text + 1; /* skip '(' */
904 end_pos = UTF_END(desc);
908 /* count the `this' pointer */
910 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
912 td->decltype = TYPE_ADR;
914 td->classref = thisclass;
917 pool->descriptors_next += sizeof(typedesc);
922 while (*utf_ptr != ')') {
923 /* parse a parameter type */
925 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
928 if (IS_2_WORD_TYPE(td->type))
932 pool->descriptors_next += sizeof(typedesc);
936 utf_ptr++; /* skip ')' */
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. */
943 if (mflags == ACC_UNDEF) {
944 td->classref = thisclass;
946 pool->descriptors_next += sizeof(typedesc);
949 /* parse return type */
951 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
955 md->paramcount = paramcount;
956 md->paramslots = paramslots;
958 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
959 /* Otherwise we do this in stack analysis. */
961 if (mflags != ACC_UNDEF) {
962 if (md->paramcount > 0) {
963 /* allocate memory for params */
965 md->params = MNEW(paramdesc, md->paramcount);
968 md->params = METHODDESC_NOPARAMS;
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... */
976 #if defined(ENABLE_JIT)
977 # if defined(ENABLE_INTRP)
984 /* params will be allocated later by
985 descriptor_params_from_paramtypes if necessary */
990 *(pool->descriptor_kind_next++) = 'm';
992 d->parseddesc.md = md;
997 /* descriptor_params_from_paramtypes *******************************************
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.
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.
1011 true.............the paramdescs were created successfully
1012 false............an exception has been thrown
1017 *******************************************************************************/
1019 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1024 assert(md->params == NULL);
1025 assert(mflags != ACC_UNDEF);
1027 td = md->paramtypes;
1029 /* check for `this' pointer */
1031 if (!(mflags & ACC_STATIC)) {
1032 constant_classref *thisclass;
1034 /* fetch class reference from reserved param slot */
1035 thisclass = td[md->paramcount].classref;
1038 if (md->paramcount > 0) {
1039 /* shift param types by 1 argument */
1040 MMOVE(td + 1, td, typedesc, md->paramcount);
1043 /* fill in first argument `this' */
1045 td->type = TYPE_ADR;
1046 td->decltype = TYPE_ADR;
1048 td->classref = thisclass;
1054 /* if the method has params, process them */
1056 if (md->paramcount > 0) {
1057 /* allocate memory for params */
1059 md->params = MNEW(paramdesc, md->paramcount);
1062 md->params = METHODDESC_NOPARAMS;
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
1070 #if defined(ENABLE_JIT)
1071 # if defined(ENABLE_INTRP)
1081 /* descriptor_pool_get_parsed_descriptors **************************************
1083 Return a pointer to the block of parsed descriptors
1086 pool.............the descriptor_pool
1089 *size............if size is non-NULL, this is set to the size of the
1090 parsed descriptor block (in u1)
1093 a pointer to the block of parsed descriptors
1096 descriptor_pool_alloc_parsed_descriptors must be called (once)
1097 before this function is used.
1099 *******************************************************************************/
1102 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1105 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1108 *size = pool->descriptorsize;
1110 return pool->descriptors;
1114 /* descriptor_pool_get_sizes ***************************************************
1116 Get the sizes of the class reference table and the parsed descriptors
1119 pool.............the descriptor_pool
1122 *classrefsize....set to size of the class reference table
1123 *descsize........set to size of the parsed descriptors
1126 This function may only be called after both
1127 descriptor_pool_create_classrefs, and
1128 descriptor_pool_alloc_parsed_descriptors
1131 *******************************************************************************/
1134 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1137 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1138 assert(pool->classrefs);
1139 assert(classrefsize);
1142 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1143 *descsize = pool->descriptorsize;
1147 /****************************************************************************/
1149 /****************************************************************************/
1152 /* descriptor_debug_print_typedesc *********************************************
1154 Print the given typedesc to the given stream
1157 file.............stream to print to
1158 d................the parsed descriptor
1160 *******************************************************************************/
1163 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1168 fprintf(file,"(typedesc *)NULL");
1172 if (d->type == TYPE_ADR) {
1174 utf_fprint_printable_ascii(file,d->classref->name);
1176 fprintf(file,"<class=NULL>");
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;
1194 fprintf(file,"[%d]",d->arraydim);
1197 /* descriptor_debug_print_paramdesc ********************************************
1199 Print the given paramdesc to the given stream
1202 file.............stream to print to
1203 d................the parameter descriptor
1205 *******************************************************************************/
1208 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1211 fprintf(file,"(paramdesc *)NULL");
1216 fprintf(file,"<m%d>",d->regoff);
1219 fprintf(file,"<r%d>",d->regoff);
1223 /* descriptor_debug_print_methoddesc *******************************************
1225 Print the given methoddesc to the given stream
1228 file.............stream to print to
1229 d................the parsed descriptor
1231 *******************************************************************************/
1234 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1239 fprintf(file,"(methoddesc *)NULL");
1244 for (i=0; i<d->paramcount; ++i) {
1247 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1249 descriptor_debug_print_paramdesc(file,d->params + i);
1252 if (d->params == METHODDESC_NOPARAMS)
1253 fputs("<NOPARAMS>",file);
1255 descriptor_debug_print_typedesc(file,&(d->returntype));
1258 /* descriptor_pool_debug_dump **************************************************
1260 Print the state of the descriptor_pool to the given stream
1263 pool.............the descriptor_pool
1264 file.............stream to print to
1266 *******************************************************************************/
1269 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1276 fprintf(file,"======[descriptor_pool for ");
1277 utf_fprint_printable_ascii(file,pool->referer->name);
1278 fprintf(file,"]======\n");
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)));
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];
1292 fprintf(file," %4d: ",c->index);
1293 utf_fprint_printable_ascii(file,c->name);
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];
1303 fprintf(file," %p: ",c->parseddesc.any);
1304 utf_fprint_printable_ascii(file,c->desc);
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);
1316 if (pool->descriptor_kind) {
1317 kind = pool->descriptor_kind;
1319 while (pos < (pool->descriptors + size)) {
1320 fprintf(file," %p: ",pos);
1323 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1324 pos += sizeof(typedesc);
1327 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1328 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1329 pos += sizeof(methoddesc) - sizeof(typedesc);
1332 fprintf(file,"INVALID KIND");
1338 while (size >= sizeof(voidptr)) {
1339 fprintf(file," %p\n",*((voidptr*)pos));
1340 pos += sizeof(voidptr);
1341 size -= sizeof(voidptr);
1346 fprintf(file,"==========================================================\n");
1348 #endif /* !defined(NDEBUG) */
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 * ---------------------------------------------------------------------
1357 * indent-tabs-mode: t
1361 * vim:noexpandtab:sw=4:ts=4: