1 /* src/vm/descriptor.c - checking and parsing of field / method descriptors
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
29 Changes: Christian Thalinger
32 $Id: descriptor.c 5171 2006-07-25 13:52:38Z twisti $
45 #include "mm/memory.h"
46 #include "vm/descriptor.h"
47 #include "vm/exceptions.h"
48 #include "vm/options.h"
49 #include "vm/resolve.h"
50 #include "vm/stringlocal.h"
53 /* constants (private to descriptor.c) ****************************************/
55 /* initial number of entries for the classrefhash of a descriptor_pool */
56 /* (currently the hash is never grown!) */
57 #define CLASSREFHASH_INIT_SIZE 64
59 /* initial number of entries for the descriptorhash of a descriptor_pool */
60 /* (currently the hash is never grown!) */
61 #define DESCRIPTORHASH_INIT_SIZE 128
63 /* data structures (private to descriptor.c) **********************************/
65 typedef struct classref_hash_entry classref_hash_entry;
66 typedef struct descriptor_hash_entry descriptor_hash_entry;
68 /* entry struct for the classrefhash of descriptor_pool */
69 struct classref_hash_entry {
70 classref_hash_entry *hashlink; /* for hash chaining */
71 utf *name; /* name of the class refered to */
72 u2 index; /* index into classref table */
75 /* entry struct for the descriptorhash of descriptor_pool */
76 struct descriptor_hash_entry {
77 descriptor_hash_entry *hashlink;
79 parseddesc parseddesc;
80 s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
84 /****************************************************************************/
85 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
86 /****************************************************************************/
88 /* SKIP_FIELDDESCRIPTOR:
89 * utf_ptr must point to the first character of a field descriptor.
90 * After the macro call utf_ptr points to the first character after
91 * the field descriptor.
93 * CAUTION: This macro does not check for an unexpected end of the
94 * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
96 #define SKIP_FIELDDESCRIPTOR(utf_ptr) \
97 do { while (*(utf_ptr)=='[') (utf_ptr)++; \
98 if (*(utf_ptr)++=='L') \
99 while(*(utf_ptr)++ != ';') /* skip */; } while(0)
101 /* SKIP_FIELDDESCRIPTOR_SAFE:
102 * utf_ptr must point to the first character of a field descriptor.
103 * After the macro call utf_ptr points to the first character after
104 * the field descriptor.
107 * utf_ptr....points to first char of descriptor
108 * end_ptr....points to first char after the end of the string
109 * errorflag..must be initialized (to false) by the caller!
111 * utf_ptr....points to first char after the descriptor
112 * errorflag..set to true if the string ended unexpectedly
114 #define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
115 do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
116 if ((utf_ptr) == (end_ptr)) \
117 (errorflag) = true; \
119 if (*(utf_ptr)++=='L') { \
120 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
122 if ((utf_ptr)[-1] != ';') \
123 (errorflag) = true; }} while(0)
126 /****************************************************************************/
128 /****************************************************************************/
130 /*#define DESCRIPTOR_VERBOSE*/
132 /****************************************************************************/
134 /****************************************************************************/
136 /* descriptor_to_basic_type ****************************************************
138 Return the basic type to use for a value with this descriptor.
141 utf..............descriptor utf string
147 This function assumes that the descriptor has passed
148 descriptor_pool_add checks and that it does not start with '('.
150 *******************************************************************************/
152 u2 descriptor_to_basic_type(utf *descriptor)
154 assert(descriptor->blength >= 1);
156 switch (descriptor->text[0]) {
161 case 'Z': return TYPE_INT;
162 case 'D': return TYPE_DBL;
163 case 'F': return TYPE_FLT;
164 case 'J': return TYPE_LNG;
166 case '[': return TYPE_ADR;
171 return 0; /* keep the compiler happy */
174 /* descriptor_typesize**** ****************************************************
176 Return the size in bytes needed for the given type.
179 td..............typedesc describing the type
184 *******************************************************************************/
186 u2 descriptor_typesize(typedesc *td)
191 case TYPE_INT: return 4;
192 case TYPE_LNG: return 8;
193 case TYPE_FLT: return 4;
194 case TYPE_DBL: return 8;
195 case TYPE_ADR: return sizeof(voidptr);
200 return 0; /* keep the compiler happy */
203 /* name_from_descriptor ********************************************************
205 Return the class name indicated by the given descriptor
206 (Internally used helper function)
209 c................class containing the descriptor
210 utf_ptr..........first character of descriptor
211 end_ptr..........first character after the end of the string
212 mode.............a combination (binary or) of the following flags:
214 (Flags marked with * are the default settings.)
216 How to handle "V" descriptors:
218 * DESCRIPTOR_VOID.....handle it like other primitive types
219 DESCRIPTOR_NOVOID...treat it as an error
221 How to deal with extra characters after the end of the
224 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
225 DESCRIPTOR_CHECKEND.....treat them as an error
228 *next............if non-NULL, *next is set to the first character after
229 the descriptor. (Undefined if an error occurs.)
230 *name............set to the utf name of the class
233 true.............descriptor parsed successfully
234 false............an exception has been thrown
236 *******************************************************************************/
238 #define DESCRIPTOR_VOID 0 /* default */
239 #define DESCRIPTOR_NOVOID 0x0040
240 #define DESCRIPTOR_NOCHECKEND 0 /* default */
241 #define DESCRIPTOR_CHECKEND 0x1000
244 name_from_descriptor(classinfo *c,
245 char *utf_ptr, char *end_ptr,
246 char **next, int mode, utf **name)
248 char *start = utf_ptr;
257 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
259 if (mode & DESCRIPTOR_CHECKEND)
260 error |= (utf_ptr != end_ptr);
263 if (next) *next = utf_ptr;
267 if (mode & DESCRIPTOR_NOVOID)
285 *name = utf_new(start, utf_ptr - start);
290 *exceptionptr = new_classformaterror(c,"invalid descriptor");
295 /* descriptor_to_typedesc ******************************************************
297 Parse the given type descriptor and fill a typedesc struct
298 (Internally used helper function)
301 pool.............the descriptor pool
302 utf_ptr..........points to first character of type descriptor
303 end_pos..........points after last character of the whole descriptor
306 *next............set to next character after type descriptor
307 *d...............filled with parsed information
310 true.............parsing succeeded
311 false............an exception has been thrown
313 *******************************************************************************/
316 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
317 char **next, typedesc *td)
321 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
325 /* a reference type */
327 td->decltype = TYPE_ADR;
329 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
331 td->classref = descriptor_pool_lookup_classref(pool, name);
334 /* a primitive type */
337 td->decltype = PRIMITIVETYPE_BYTE;
341 td->decltype = PRIMITIVETYPE_CHAR;
345 td->decltype = PRIMITIVETYPE_SHORT;
349 td->decltype = PRIMITIVETYPE_BOOLEAN;
353 td->decltype = PRIMITIVETYPE_INT;
357 td->decltype = PRIMITIVETYPE_DOUBLE;
361 td->decltype = PRIMITIVETYPE_FLOAT;
365 td->decltype = PRIMITIVETYPE_LONG;
369 td->decltype = PRIMITIVETYPE_VOID;
370 td->type = TYPE_VOID;
384 /* descriptor_pool_new *********************************************************
386 Allocate a new descriptor_pool
389 referer..........class for which to create the pool
392 a pointer to the new descriptor_pool
394 *******************************************************************************/
397 descriptor_pool_new(classinfo *referer)
399 descriptor_pool *pool;
403 pool = DNEW(descriptor_pool);
406 pool->referer = referer;
407 pool->fieldcount = 0;
408 pool->methodcount = 0;
409 pool->paramcount = 0;
410 pool->descriptorsize = 0;
411 pool->descriptors = NULL;
412 pool->descriptors_next = NULL;
413 pool->classrefs = NULL;
414 pool->descriptor_kind = NULL;
415 pool->descriptor_kind_next = NULL;
417 hashsize = CLASSREFHASH_INIT_SIZE;
418 pool->classrefhash.size = hashsize;
419 pool->classrefhash.entries = 0;
420 pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
421 for (slot=0; slot<hashsize; ++slot)
422 pool->classrefhash.ptr[slot] = NULL;
424 hashsize = DESCRIPTORHASH_INIT_SIZE;
425 pool->descriptorhash.size = hashsize;
426 pool->descriptorhash.entries = 0;
427 pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
428 for (slot=0; slot<hashsize; ++slot)
429 pool->descriptorhash.ptr[slot] = NULL;
435 /* descriptor_pool_add_class ***************************************************
437 Add the given class reference to the pool
440 pool.............the descriptor_pool
441 name.............the class reference to add
444 true.............reference has been added
445 false............an exception has been thrown
447 *******************************************************************************/
450 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
453 classref_hash_entry *c;
458 #ifdef DESCRIPTOR_VERBOSE
459 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
460 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
463 /* find a place in the hashtable */
465 key = utf_hashkey(name->text, name->blength);
466 slot = key & (pool->classrefhash.size - 1);
467 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
471 return true; /* already stored */
475 /* check if the name is a valid classname */
477 if (!is_valid_name(name->text,UTF_END(name))) {
478 *exceptionptr = new_classformaterror(pool->referer,
479 "Invalid class name");
480 return false; /* exception */
483 /* XXX check maximum array dimension */
485 c = DNEW(classref_hash_entry);
487 c->index = pool->classrefhash.entries++;
488 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
489 pool->classrefhash.ptr[slot] = c;
495 /* descriptor_pool_add *********************************************************
497 Check the given descriptor and add it to the pool
500 pool.............the descriptor_pool
501 desc.............the descriptor to add. Maybe a field or method desc.
504 *paramslots......if non-NULL, set to the number of parameters.
505 LONG and DOUBLE are counted twice
508 true.............descriptor has been added
509 false............an exception has been thrown
511 *******************************************************************************/
514 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
517 descriptor_hash_entry *d;
523 #ifdef DESCRIPTOR_VERBOSE
524 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
525 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
531 /* find a place in the hashtable */
533 key = utf_hashkey(desc->text, desc->blength);
534 slot = key & (pool->descriptorhash.size - 1);
535 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
537 /* Save all method descriptors in the hashtable, since the parsed */
538 /* descriptor may vary between differenf methods (static vs. non-static). */
540 utf_ptr = desc->text;
542 if (*utf_ptr != '(') {
544 if (d->desc == desc) {
546 *paramslots = d->paramslots;
547 return true; /* already stored */
553 /* add the descriptor to the pool */
555 d = DNEW(descriptor_hash_entry);
557 d->parseddesc.any = NULL;
558 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
559 pool->descriptorhash.ptr[slot] = d;
561 /* now check the descriptor */
563 end_pos = UTF_END(desc);
565 if (*utf_ptr == '(') {
566 /* a method descriptor */
571 /* check arguments */
573 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
576 /* We cannot count the `this' argument here because
577 * we don't know if the method is static. */
579 if (*utf_ptr == 'J' || *utf_ptr == 'D')
584 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
585 DESCRIPTOR_NOVOID, &name))
589 if (!descriptor_pool_add_class(pool, name))
593 if (utf_ptr == end_pos) {
594 *exceptionptr = new_classformaterror(pool->referer,"Missing ')' in method descriptor");
598 utf_ptr++; /* skip ')' */
600 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
601 DESCRIPTOR_CHECKEND, &name))
605 if (!descriptor_pool_add_class(pool,name))
608 if (argcount > 255) {
610 new_classformaterror(pool->referer,"Too many arguments in signature");
615 /* a field descriptor */
619 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
620 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
625 if (!descriptor_pool_add_class(pool,name))
629 d->paramslots = argcount;
632 *paramslots = argcount;
638 /* descriptor_pool_create_classrefs ********************************************
640 Create a table containing all the classrefs which were added to the pool
643 pool.............the descriptor_pool
646 *count...........if count is non-NULL, this is set to the number
647 of classrefs in the table
650 a pointer to the constant_classref table
652 *******************************************************************************/
655 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
659 classref_hash_entry *c;
660 constant_classref *ref;
664 nclasses = pool->classrefhash.entries;
665 pool->classrefs = MNEW(constant_classref,nclasses);
667 /* fill the constant_classref structs */
669 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
670 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
672 ref = pool->classrefs + c->index;
673 CLASSREF_INIT(*ref, pool->referer, c->name);
681 return pool->classrefs;
685 /* descriptor_pool_lookup_classref *********************************************
687 Return the constant_classref for the given class name
690 pool.............the descriptor_pool
691 classname........name of the class to look up
694 a pointer to the constant_classref, or
695 NULL if an exception has been thrown
697 *******************************************************************************/
700 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
703 classref_hash_entry *c;
706 assert(pool->classrefs);
709 key = utf_hashkey(classname->text, classname->blength);
710 slot = key & (pool->classrefhash.size - 1);
711 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
714 if (c->name == classname)
715 return pool->classrefs + c->index;
719 *exceptionptr = new_internalerror("Class reference not found in descriptor pool");
724 /* descriptor_pool_alloc_parsed_descriptors ************************************
726 Allocate space for the parsed descriptors
729 pool.............the descriptor_pool
732 This function must be called after all descriptors have been added
733 with descriptor_pool_add.
735 *******************************************************************************/
738 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
744 /* TWISTI: paramcount + 1: we don't know if the method is static or */
745 /* not, i have no better solution yet. */
748 pool->fieldcount * sizeof(typedesc) +
749 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
750 pool->paramcount * sizeof(typedesc) +
751 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
753 pool->descriptorsize = size;
755 pool->descriptors = MNEW(u1, size);
756 pool->descriptors_next = pool->descriptors;
759 size = pool->fieldcount + pool->methodcount;
761 pool->descriptor_kind = DMNEW(u1, size);
762 pool->descriptor_kind_next = pool->descriptor_kind;
767 /* descriptor_pool_parse_field_descriptor **************************************
769 Parse the given field descriptor
772 pool.............the descriptor_pool
773 desc.............the field descriptor
776 a pointer to the parsed field descriptor, or
777 NULL if an exception has been thrown
780 descriptor_pool_alloc_parsed_descriptors must be called (once)
781 before this function is used.
783 *******************************************************************************/
786 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
789 descriptor_hash_entry *d;
793 assert(pool->descriptors);
794 assert(pool->descriptors_next);
796 /* lookup the descriptor in the hashtable */
798 key = utf_hashkey(desc->text, desc->blength);
799 slot = key & (pool->descriptorhash.size - 1);
800 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
803 if (d->desc == desc) {
805 if (d->parseddesc.fd)
806 return d->parseddesc.fd;
814 if (desc->text[0] == '(') {
815 *exceptionptr = new_classformaterror(pool->referer,
816 "Method descriptor used in field reference");
820 td = (typedesc *) pool->descriptors_next;
821 pool->descriptors_next += sizeof(typedesc);
823 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
826 *(pool->descriptor_kind_next++) = 'f';
828 d->parseddesc.fd = td;
834 /* descriptor_pool_parse_method_descriptor *************************************
836 Parse the given method descriptor
839 pool.............the descriptor_pool
840 desc.............the method descriptor
841 mflags...........the method flags
842 thisclass........classref to the class containing the method.
843 This is ignored if mflags contains ACC_STATIC.
844 The classref is stored for inserting the 'this' argument.
847 a pointer to the parsed method descriptor, or
848 NULL if an exception has been thrown
851 descriptor_pool_alloc_parsed_descriptors must be called
852 (once) before this function is used.
854 *******************************************************************************/
857 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
858 s4 mflags,constant_classref *thisclass)
861 descriptor_hash_entry *d;
869 #ifdef DESCRIPTOR_VERBOSE
870 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
871 (void*)pool,(int)mflags,(void*)thisclass);
872 utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
876 assert(pool->descriptors);
877 assert(pool->descriptors_next);
879 /* check that it is a method descriptor */
881 if (desc->text[0] != '(') {
882 *exceptionptr = new_classformaterror(pool->referer,
883 "Field descriptor used in method reference");
887 /* lookup the descriptor in the hashtable */
889 key = utf_hashkey(desc->text, desc->blength);
890 slot = key & (pool->descriptorhash.size - 1);
891 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
893 /* find an un-parsed descriptor */
897 if (!d->parseddesc.md)
904 md = (methoddesc *) pool->descriptors_next;
905 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
907 utf_ptr = desc->text + 1; /* skip '(' */
908 end_pos = UTF_END(desc);
912 /* count the `this' pointer */
914 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
916 td->decltype = TYPE_ADR;
918 td->classref = thisclass;
921 pool->descriptors_next += sizeof(typedesc);
926 while (*utf_ptr != ')') {
927 /* parse a parameter type */
929 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
932 if (IS_2_WORD_TYPE(td->type))
936 pool->descriptors_next += sizeof(typedesc);
940 utf_ptr++; /* skip ')' */
942 /* Skip possible `this' pointer in paramtypes array to allow a possible */
943 /* memory move later in parse. */
944 /* We store the thisclass reference, so we can later correctly fill in */
945 /* the parameter slot of the 'this' argument. */
947 if (mflags == ACC_UNDEF) {
948 td->classref = thisclass;
950 pool->descriptors_next += sizeof(typedesc);
953 /* parse return type */
955 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
959 md->paramcount = paramcount;
960 md->paramslots = paramslots;
962 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
963 /* Otherwise we do this in stack analysis. */
965 if (mflags != ACC_UNDEF) {
966 if (md->paramcount > 0) {
967 /* allocate memory for params */
969 md->params = MNEW(paramdesc, md->paramcount);
972 md->params = METHODDESC_NOPARAMS;
975 /* fill the paramdesc */
976 /* md_param_alloc has to be called if md->paramcount == 0,
977 too, so it can make the reservation for the Linkage Area,
978 Return Register... */
980 #if defined(ENABLE_JIT)
981 # if defined(ENABLE_INTRP)
988 /* params will be allocated later by
989 descriptor_params_from_paramtypes if necessary */
994 *(pool->descriptor_kind_next++) = 'm';
996 d->parseddesc.md = md;
1001 /* descriptor_params_from_paramtypes *******************************************
1003 Create the paramdescs for a method descriptor. This function is called
1004 when we know whether the method is static or not. This function may only
1005 be called once for each methoddesc, and only if md->params == NULL.
1008 md...............the parsed method descriptor
1009 md->params MUST be NULL.
1010 mflags...........the ACC_* access flags of the method. Only the
1011 ACC_STATIC bit is checked.
1012 The value ACC_UNDEF is NOT allowed.
1015 true.............the paramdescs were created successfully
1016 false............an exception has been thrown
1021 *******************************************************************************/
1023 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1028 assert(md->params == NULL);
1029 assert(mflags != ACC_UNDEF);
1031 td = md->paramtypes;
1033 /* check for `this' pointer */
1035 if (!(mflags & ACC_STATIC)) {
1036 constant_classref *thisclass;
1038 /* fetch class reference from reserved param slot */
1039 thisclass = td[md->paramcount].classref;
1042 if (md->paramcount > 0) {
1043 /* shift param types by 1 argument */
1044 MMOVE(td + 1, td, typedesc, md->paramcount);
1047 /* fill in first argument `this' */
1049 td->type = TYPE_ADR;
1050 td->decltype = TYPE_ADR;
1052 td->classref = thisclass;
1058 /* if the method has params, process them */
1060 if (md->paramcount > 0) {
1061 /* allocate memory for params */
1063 md->params = MNEW(paramdesc, md->paramcount);
1066 md->params = METHODDESC_NOPARAMS;
1069 /* fill the paramdesc */
1070 /* md_param_alloc has to be called if md->paramcount == 0, too, so
1071 it can make the reservation for the Linkage Area, Return
1074 #if defined(ENABLE_JIT)
1075 # if defined(ENABLE_INTRP)
1085 /* descriptor_pool_get_parsed_descriptors **************************************
1087 Return a pointer to the block of parsed descriptors
1090 pool.............the descriptor_pool
1093 *size............if size is non-NULL, this is set to the size of the
1094 parsed descriptor block (in u1)
1097 a pointer to the block of parsed descriptors
1100 descriptor_pool_alloc_parsed_descriptors must be called (once)
1101 before this function is used.
1103 *******************************************************************************/
1106 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1109 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1112 *size = pool->descriptorsize;
1114 return pool->descriptors;
1118 /* descriptor_pool_get_sizes ***************************************************
1120 Get the sizes of the class reference table and the parsed descriptors
1123 pool.............the descriptor_pool
1126 *classrefsize....set to size of the class reference table
1127 *descsize........set to size of the parsed descriptors
1130 This function may only be called after both
1131 descriptor_pool_create_classrefs, and
1132 descriptor_pool_alloc_parsed_descriptors
1135 *******************************************************************************/
1138 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1141 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1142 assert(pool->classrefs);
1143 assert(classrefsize);
1146 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1147 *descsize = pool->descriptorsize;
1151 /****************************************************************************/
1153 /****************************************************************************/
1156 /* descriptor_debug_print_typedesc *********************************************
1158 Print the given typedesc to the given stream
1161 file.............stream to print to
1162 d................the parsed descriptor
1164 *******************************************************************************/
1167 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1172 fprintf(file,"(typedesc *)NULL");
1176 if (d->type == TYPE_ADR) {
1178 utf_fprint_printable_ascii(file,d->classref->name);
1180 fprintf(file,"<class=NULL>");
1183 switch (d->decltype) {
1184 case PRIMITIVETYPE_INT : ch='I'; break;
1185 case PRIMITIVETYPE_CHAR : ch='C'; break;
1186 case PRIMITIVETYPE_BYTE : ch='B'; break;
1187 case PRIMITIVETYPE_SHORT : ch='S'; break;
1188 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1189 case PRIMITIVETYPE_LONG : ch='J'; break;
1190 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1191 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1192 case PRIMITIVETYPE_VOID : ch='V'; break;
1198 fprintf(file,"[%d]",d->arraydim);
1201 /* descriptor_debug_print_paramdesc ********************************************
1203 Print the given paramdesc to the given stream
1206 file.............stream to print to
1207 d................the parameter descriptor
1209 *******************************************************************************/
1212 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1215 fprintf(file,"(paramdesc *)NULL");
1220 fprintf(file,"<m%d>",d->regoff);
1223 fprintf(file,"<r%d>",d->regoff);
1227 /* descriptor_debug_print_methoddesc *******************************************
1229 Print the given methoddesc to the given stream
1232 file.............stream to print to
1233 d................the parsed descriptor
1235 *******************************************************************************/
1238 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1243 fprintf(file,"(methoddesc *)NULL");
1248 for (i=0; i<d->paramcount; ++i) {
1251 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1253 descriptor_debug_print_paramdesc(file,d->params + i);
1256 if (d->params == METHODDESC_NOPARAMS)
1257 fputs("<NOPARAMS>",file);
1259 descriptor_debug_print_typedesc(file,&(d->returntype));
1262 /* descriptor_pool_debug_dump **************************************************
1264 Print the state of the descriptor_pool to the given stream
1267 pool.............the descriptor_pool
1268 file.............stream to print to
1270 *******************************************************************************/
1273 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1280 fprintf(file,"======[descriptor_pool for ");
1281 utf_fprint_printable_ascii(file,pool->referer->name);
1282 fprintf(file,"]======\n");
1284 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1285 fprintf(file,"methodcount: %d\n",pool->methodcount);
1286 fprintf(file,"paramcount: %d\n",pool->paramcount);
1287 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1288 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1289 fprintf(file,"classrefsize: %d bytes\n",
1290 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1292 fprintf(file,"class references:\n");
1293 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1294 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1296 fprintf(file," %4d: ",c->index);
1297 utf_fprint_printable_ascii(file,c->name);
1303 fprintf(file,"hashed descriptors:\n");
1304 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1305 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1307 fprintf(file," %p: ",c->parseddesc.any);
1308 utf_fprint_printable_ascii(file,c->desc);
1314 fprintf(file,"descriptors:\n");
1315 if (pool->descriptors) {
1316 pos = pool->descriptors;
1317 size = pool->descriptors_next - pool->descriptors;
1318 fprintf(file," size: %d bytes\n",size);
1320 if (pool->descriptor_kind) {
1321 kind = pool->descriptor_kind;
1323 while (pos < (pool->descriptors + size)) {
1324 fprintf(file," %p: ",pos);
1327 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1328 pos += sizeof(typedesc);
1331 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1332 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1333 pos += sizeof(methoddesc) - sizeof(typedesc);
1336 fprintf(file,"INVALID KIND");
1342 while (size >= sizeof(voidptr)) {
1343 fprintf(file," %p\n",*((voidptr*)pos));
1344 pos += sizeof(voidptr);
1345 size -= sizeof(voidptr);
1350 fprintf(file,"==========================================================\n");
1352 #endif /* !defined(NDEBUG) */
1355 * These are local overrides for various environment variables in Emacs.
1356 * Please do not remove this and leave it at the end of the file, where
1357 * Emacs will automagically detect them.
1358 * ---------------------------------------------------------------------
1361 * indent-tabs-mode: t
1365 * vim:noexpandtab:sw=4:ts=4: