1 /* src/vm/descriptor.c - checking and parsing of field / method descriptors
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "mm/memory.h"
36 #include "vm/descriptor.h"
37 #include "vm/exceptions.hpp"
38 #include "vm/options.h"
39 #include "vm/primitive.hpp"
42 #include "vm/jit/abi.h"
45 /* constants (private to descriptor.c) ****************************************/
47 /* initial number of entries for the classrefhash of a descriptor_pool */
48 /* (currently the hash is never grown!) */
49 #define CLASSREFHASH_INIT_SIZE 64
51 /* initial number of entries for the descriptorhash of a descriptor_pool */
52 /* (currently the hash is never grown!) */
53 #define DESCRIPTORHASH_INIT_SIZE 128
55 /* data structures (private to descriptor.c) **********************************/
57 typedef struct classref_hash_entry classref_hash_entry;
58 typedef struct descriptor_hash_entry descriptor_hash_entry;
60 /* entry struct for the classrefhash of descriptor_pool */
61 struct classref_hash_entry {
62 classref_hash_entry *hashlink; /* for hash chaining */
63 utf *name; /* name of the class refered to */
64 u2 index; /* index into classref table */
67 /* entry struct for the descriptorhash of descriptor_pool */
68 struct descriptor_hash_entry {
69 descriptor_hash_entry *hashlink;
71 parseddesc_t parseddesc;
72 s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
76 /****************************************************************************/
77 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
78 /****************************************************************************/
80 /* SKIP_FIELDDESCRIPTOR:
81 * utf_ptr must point to the first character of a field descriptor.
82 * After the macro call utf_ptr points to the first character after
83 * the field descriptor.
85 * CAUTION: This macro does not check for an unexpected end of the
86 * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
88 #define SKIP_FIELDDESCRIPTOR(utf_ptr) \
89 do { while (*(utf_ptr)=='[') (utf_ptr)++; \
90 if (*(utf_ptr)++=='L') \
91 while(*(utf_ptr)++ != ';') /* skip */; } while(0)
93 /* SKIP_FIELDDESCRIPTOR_SAFE:
94 * utf_ptr must point to the first character of a field descriptor.
95 * After the macro call utf_ptr points to the first character after
96 * the field descriptor.
99 * utf_ptr....points to first char of descriptor
100 * end_ptr....points to first char after the end of the string
101 * errorflag..must be initialized (to false) by the caller!
103 * utf_ptr....points to first char after the descriptor
104 * errorflag..set to true if the string ended unexpectedly
106 #define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
107 do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
108 if ((utf_ptr) == (end_ptr)) \
109 (errorflag) = true; \
111 if (*(utf_ptr)++=='L') { \
112 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
114 if ((utf_ptr)[-1] != ';') \
115 (errorflag) = true; }} while(0)
118 /****************************************************************************/
120 /****************************************************************************/
122 /*#define DESCRIPTOR_VERBOSE*/
124 /****************************************************************************/
126 /****************************************************************************/
128 /* descriptor_to_basic_type ****************************************************
130 Return the basic type to use for a value with this descriptor.
133 utf..............descriptor utf string
139 This function assumes that the descriptor has passed
140 descriptor_pool_add checks and that it does not start with '('.
142 *******************************************************************************/
144 int descriptor_to_basic_type(utf *descriptor)
146 assert(descriptor->blength >= 1);
148 switch (descriptor->text[0]) {
170 vm_abort("descriptor_to_basic_type: invalid type %c",
171 descriptor->text[0]);
174 /* keep the compiler happy */
180 /* descriptor_typesize *********************************************************
182 Return the size in bytes needed for the given type.
185 td..............typedesc describing the type
190 *******************************************************************************/
192 int descriptor_typesize(typedesc *td)
206 return SIZEOF_VOID_P;
209 vm_abort("descriptor_typesize: invalid type %d", td->type);
212 /* keep the compiler happy */
218 /* name_from_descriptor ********************************************************
220 Return the class name indicated by the given descriptor
221 (Internally used helper function)
224 c................class containing the descriptor
225 utf_ptr..........first character of descriptor
226 end_ptr..........first character after the end of the string
227 mode.............a combination (binary or) of the following flags:
229 (Flags marked with * are the default settings.)
231 How to handle "V" descriptors:
233 * DESCRIPTOR_VOID.....handle it like other primitive types
234 DESCRIPTOR_NOVOID...treat it as an error
236 How to deal with extra characters after the end of the
239 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
240 DESCRIPTOR_CHECKEND.....treat them as an error
243 *next............if non-NULL, *next is set to the first character after
244 the descriptor. (Undefined if an error occurs.)
245 *name............set to the utf name of the class
248 true.............descriptor parsed successfully
249 false............an exception has been thrown
251 *******************************************************************************/
253 #define DESCRIPTOR_VOID 0 /* default */
254 #define DESCRIPTOR_NOVOID 0x0040
255 #define DESCRIPTOR_NOCHECKEND 0 /* default */
256 #define DESCRIPTOR_CHECKEND 0x1000
259 name_from_descriptor(classinfo *c,
260 char *utf_ptr, char *end_ptr,
261 char **next, int mode, utf **name)
263 char *start = utf_ptr;
272 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
274 if (mode & DESCRIPTOR_CHECKEND)
275 error |= (utf_ptr != end_ptr);
278 if (next) *next = utf_ptr;
282 if (mode & DESCRIPTOR_NOVOID)
300 *name = utf_new(start, utf_ptr - start);
305 exceptions_throw_classformaterror(c, "Invalid descriptor");
310 /* descriptor_to_typedesc ******************************************************
312 Parse the given type descriptor and fill a typedesc struct
313 (Internally used helper function)
316 pool.............the descriptor pool
317 utf_ptr..........points to first character of type descriptor
318 end_pos..........points after last character of the whole descriptor
321 *next............set to next character after type descriptor
322 *d...............filled with parsed information
325 true.............parsing succeeded
326 false............an exception has been thrown
328 *******************************************************************************/
331 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
332 char **next, typedesc *td)
336 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
340 /* a reference type */
342 td->primitivetype = TYPE_ADR;
344 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
346 td->classref = descriptor_pool_lookup_classref(pool, name);
349 /* a primitive type */
352 td->primitivetype = PRIMITIVETYPE_BYTE;
356 td->primitivetype = PRIMITIVETYPE_CHAR;
360 td->primitivetype = PRIMITIVETYPE_SHORT;
364 td->primitivetype = PRIMITIVETYPE_BOOLEAN;
368 td->primitivetype = PRIMITIVETYPE_INT;
372 td->primitivetype = PRIMITIVETYPE_DOUBLE;
376 td->primitivetype = PRIMITIVETYPE_FLOAT;
380 td->primitivetype = PRIMITIVETYPE_LONG;
384 td->primitivetype = PRIMITIVETYPE_VOID;
385 td->type = TYPE_VOID;
399 /* descriptor_pool_new *********************************************************
401 Allocate a new descriptor_pool
404 referer..........class for which to create the pool
407 a pointer to the new descriptor_pool
409 *******************************************************************************/
412 descriptor_pool_new(classinfo *referer)
414 descriptor_pool *pool;
418 pool = DNEW(descriptor_pool);
421 pool->referer = referer;
422 pool->fieldcount = 0;
423 pool->methodcount = 0;
424 pool->paramcount = 0;
425 pool->descriptorsize = 0;
426 pool->descriptors = NULL;
427 pool->descriptors_next = NULL;
428 pool->classrefs = NULL;
429 pool->descriptor_kind = NULL;
430 pool->descriptor_kind_next = NULL;
432 hashsize = CLASSREFHASH_INIT_SIZE;
433 pool->classrefhash.size = hashsize;
434 pool->classrefhash.entries = 0;
435 pool->classrefhash.ptr = DMNEW(void*, hashsize);
436 for (slot=0; slot<hashsize; ++slot)
437 pool->classrefhash.ptr[slot] = NULL;
439 hashsize = DESCRIPTORHASH_INIT_SIZE;
440 pool->descriptorhash.size = hashsize;
441 pool->descriptorhash.entries = 0;
442 pool->descriptorhash.ptr = DMNEW(void*, hashsize);
443 for (slot=0; slot<hashsize; ++slot)
444 pool->descriptorhash.ptr[slot] = NULL;
450 /* descriptor_pool_add_class ***************************************************
452 Add the given class reference to the pool
455 pool.............the descriptor_pool
456 name.............the class reference to add
459 true.............reference has been added
460 false............an exception has been thrown
462 *******************************************************************************/
465 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
468 classref_hash_entry *c;
473 #ifdef DESCRIPTOR_VERBOSE
474 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
475 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
478 /* find a place in the hashtable */
480 key = utf_hashkey(name->text, name->blength);
481 slot = key & (pool->classrefhash.size - 1);
482 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
486 return true; /* already stored */
490 /* check if the name is a valid classname */
492 if (!is_valid_name(name->text,UTF_END(name))) {
493 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
494 return false; /* exception */
497 /* XXX check maximum array dimension */
499 c = DNEW(classref_hash_entry);
501 c->index = pool->classrefhash.entries++;
502 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
503 pool->classrefhash.ptr[slot] = c;
509 /* descriptor_pool_add *********************************************************
511 Check the given descriptor and add it to the pool
514 pool.............the descriptor_pool
515 desc.............the descriptor to add. Maybe a field or method desc.
518 *paramslots......if non-NULL, set to the number of parameters.
519 LONG and DOUBLE are counted twice
522 true.............descriptor has been added
523 false............an exception has been thrown
525 *******************************************************************************/
528 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
531 descriptor_hash_entry *d;
537 #ifdef DESCRIPTOR_VERBOSE
538 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
539 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
545 /* find a place in the hashtable */
547 key = utf_hashkey(desc->text, desc->blength);
548 slot = key & (pool->descriptorhash.size - 1);
549 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
551 /* Save all method descriptors in the hashtable, since the parsed */
552 /* descriptor may vary between differenf methods (static vs. non-static). */
554 utf_ptr = desc->text;
556 if (*utf_ptr != '(') {
558 if (d->desc == desc) {
560 *paramslots = d->paramslots;
561 return true; /* already stored */
567 /* add the descriptor to the pool */
569 d = DNEW(descriptor_hash_entry);
571 d->parseddesc.any = NULL;
572 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
573 pool->descriptorhash.ptr[slot] = d;
575 /* now check the descriptor */
577 end_pos = UTF_END(desc);
579 if (*utf_ptr == '(') {
580 /* a method descriptor */
585 /* check arguments */
587 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
590 /* We cannot count the `this' argument here because
591 * we don't know if the method is static. */
593 if (*utf_ptr == 'J' || *utf_ptr == 'D')
598 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
599 DESCRIPTOR_NOVOID, &name))
603 if (!descriptor_pool_add_class(pool, name))
607 if (utf_ptr == end_pos) {
608 exceptions_throw_classformaterror(pool->referer,
609 "Missing ')' in method descriptor");
613 utf_ptr++; /* skip ')' */
615 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
616 DESCRIPTOR_CHECKEND, &name))
620 if (!descriptor_pool_add_class(pool,name))
623 if (argcount > 255) {
624 exceptions_throw_classformaterror(pool->referer,
625 "Too many arguments in signature");
630 /* a field descriptor */
634 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
635 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
640 if (!descriptor_pool_add_class(pool,name))
644 d->paramslots = argcount;
647 *paramslots = argcount;
653 /* descriptor_pool_create_classrefs ********************************************
655 Create a table containing all the classrefs which were added to the pool
658 pool.............the descriptor_pool
661 *count...........if count is non-NULL, this is set to the number
662 of classrefs in the table
665 a pointer to the constant_classref table
667 *******************************************************************************/
670 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
674 classref_hash_entry *c;
675 constant_classref *ref;
679 nclasses = pool->classrefhash.entries;
680 pool->classrefs = MNEW(constant_classref,nclasses);
682 /* fill the constant_classref structs */
684 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
685 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
687 ref = pool->classrefs + c->index;
688 CLASSREF_INIT(*ref, pool->referer, c->name);
696 return pool->classrefs;
700 /* descriptor_pool_lookup_classref *********************************************
702 Return the constant_classref for the given class name
705 pool.............the descriptor_pool
706 classname........name of the class to look up
709 a pointer to the constant_classref, or
710 NULL if an exception has been thrown
712 *******************************************************************************/
715 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
718 classref_hash_entry *c;
721 assert(pool->classrefs);
724 key = utf_hashkey(classname->text, classname->blength);
725 slot = key & (pool->classrefhash.size - 1);
726 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
729 if (c->name == classname)
730 return pool->classrefs + c->index;
734 exceptions_throw_internalerror("Class reference not found in descriptor pool");
739 /* descriptor_pool_alloc_parsed_descriptors ************************************
741 Allocate space for the parsed descriptors
744 pool.............the descriptor_pool
747 This function must be called after all descriptors have been added
748 with descriptor_pool_add.
750 *******************************************************************************/
753 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
759 /* TWISTI: paramcount + 1: we don't know if the method is static or */
760 /* not, i have no better solution yet. */
763 pool->fieldcount * sizeof(typedesc) +
764 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
765 pool->paramcount * sizeof(typedesc) +
766 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
768 pool->descriptorsize = size;
770 pool->descriptors = MNEW(u1, size);
771 pool->descriptors_next = pool->descriptors;
774 size = pool->fieldcount + pool->methodcount;
776 pool->descriptor_kind = DMNEW(u1, size);
777 pool->descriptor_kind_next = pool->descriptor_kind;
782 /* descriptor_pool_parse_field_descriptor **************************************
784 Parse the given field descriptor
787 pool.............the descriptor_pool
788 desc.............the field descriptor
791 a pointer to the parsed field descriptor, or
792 NULL if an exception has been thrown
795 descriptor_pool_alloc_parsed_descriptors must be called (once)
796 before this function is used.
798 *******************************************************************************/
801 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
804 descriptor_hash_entry *d;
808 assert(pool->descriptors);
809 assert(pool->descriptors_next);
811 /* lookup the descriptor in the hashtable */
813 key = utf_hashkey(desc->text, desc->blength);
814 slot = key & (pool->descriptorhash.size - 1);
815 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
818 if (d->desc == desc) {
820 if (d->parseddesc.fd)
821 return d->parseddesc.fd;
829 if (desc->text[0] == '(') {
830 exceptions_throw_classformaterror(pool->referer,
831 "Method descriptor used in field reference");
835 td = (typedesc *) pool->descriptors_next;
836 pool->descriptors_next += sizeof(typedesc);
838 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
841 *(pool->descriptor_kind_next++) = 'f';
843 d->parseddesc.fd = td;
849 /* descriptor_pool_parse_method_descriptor *************************************
851 Parse the given method descriptor
854 pool.............the descriptor_pool
855 desc.............the method descriptor
856 mflags...........the method flags
857 thisclass........classref to the class containing the method.
858 This is ignored if mflags contains ACC_STATIC.
859 The classref is stored for inserting the 'this' argument.
862 a pointer to the parsed method descriptor, or
863 NULL if an exception has been thrown
866 descriptor_pool_alloc_parsed_descriptors must be called
867 (once) before this function is used.
869 *******************************************************************************/
872 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
873 s4 mflags,constant_classref *thisclass)
876 descriptor_hash_entry *d;
884 #ifdef DESCRIPTOR_VERBOSE
885 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
886 (void*)pool,(int)mflags,(void*)thisclass);
887 utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
891 assert(pool->descriptors);
892 assert(pool->descriptors_next);
894 /* check that it is a method descriptor */
896 if (desc->text[0] != '(') {
897 exceptions_throw_classformaterror(pool->referer,
898 "Field descriptor used in method reference");
902 /* lookup the descriptor in the hashtable */
904 key = utf_hashkey(desc->text, desc->blength);
905 slot = key & (pool->descriptorhash.size - 1);
906 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
908 /* find an un-parsed descriptor */
912 if (!d->parseddesc.md)
919 md = (methoddesc *) pool->descriptors_next;
920 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
922 utf_ptr = desc->text + 1; /* skip '(' */
923 end_pos = UTF_END(desc);
927 /* count the `this' pointer */
929 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
931 td->primitivetype = TYPE_ADR;
933 td->classref = thisclass;
936 pool->descriptors_next += sizeof(typedesc);
941 while (*utf_ptr != ')') {
942 /* parse a parameter type */
944 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
947 if (IS_2_WORD_TYPE(td->type))
951 pool->descriptors_next += sizeof(typedesc);
955 utf_ptr++; /* skip ')' */
957 /* Skip possible `this' pointer in paramtypes array to allow a possible */
958 /* memory move later in parse. */
959 /* We store the thisclass reference, so we can later correctly fill in */
960 /* the parameter slot of the 'this' argument. */
962 if (mflags == ACC_UNDEF) {
963 td->classref = thisclass;
965 pool->descriptors_next += sizeof(typedesc);
968 /* parse return type */
970 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
974 md->paramcount = paramcount;
975 md->paramslots = paramslots;
977 /* If mflags != ACC_UNDEF we parse a real loaded method, so do
978 param prealloc. Otherwise we do this in stack analysis. */
980 if (mflags != ACC_UNDEF) {
981 if (md->paramcount > 0) {
982 /* allocate memory for params */
984 md->params = MNEW(paramdesc, md->paramcount);
987 md->params = METHODDESC_NOPARAMS;
990 /* fill the paramdesc */
991 /* md_param_alloc has to be called if md->paramcount == 0,
992 too, so it can make the reservation for the Linkage Area,
993 Return Register... */
995 #if defined(ENABLE_JIT)
996 # if defined(ENABLE_INTRP)
1000 /* As builtin-functions are native functions, we have
1001 to pre-allocate for the native ABI. */
1003 if (mflags & ACC_METHOD_BUILTIN)
1004 md_param_alloc_native(md);
1011 /* params will be allocated later by
1012 descriptor_params_from_paramtypes if necessary */
1017 *(pool->descriptor_kind_next++) = 'm';
1019 d->parseddesc.md = md;
1024 /* descriptor_params_from_paramtypes *******************************************
1026 Create the paramdescs for a method descriptor. This function is called
1027 when we know whether the method is static or not. This function may only
1028 be called once for each methoddesc, and only if md->params == NULL.
1031 md...............the parsed method descriptor
1032 md->params MUST be NULL.
1033 mflags...........the ACC_* access flags of the method. Only the
1034 ACC_STATIC bit is checked.
1035 The value ACC_UNDEF is NOT allowed.
1038 true.............the paramdescs were created successfully
1039 false............an exception has been thrown
1044 *******************************************************************************/
1046 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1051 assert(md->params == NULL);
1052 assert(mflags != ACC_UNDEF);
1054 td = md->paramtypes;
1056 /* check for `this' pointer */
1058 if (!(mflags & ACC_STATIC)) {
1059 constant_classref *thisclass;
1061 /* fetch class reference from reserved param slot */
1062 thisclass = td[md->paramcount].classref;
1065 if (md->paramcount > 0) {
1066 /* shift param types by 1 argument */
1067 MMOVE(td + 1, td, typedesc, md->paramcount);
1070 /* fill in first argument `this' */
1072 td->type = TYPE_ADR;
1073 td->primitivetype = TYPE_ADR;
1075 td->classref = thisclass;
1081 /* if the method has params, process them */
1083 if (md->paramcount > 0) {
1084 /* allocate memory for params */
1086 md->params = MNEW(paramdesc, md->paramcount);
1089 md->params = METHODDESC_NOPARAMS;
1092 /* fill the paramdesc */
1093 /* md_param_alloc has to be called if md->paramcount == 0, too, so
1094 it can make the reservation for the Linkage Area, Return
1097 #if defined(ENABLE_JIT)
1098 # if defined(ENABLE_INTRP)
1102 /* As builtin-functions are native functions, we have to
1103 pre-allocate for the native ABI. */
1105 if (mflags & ACC_METHOD_BUILTIN)
1106 md_param_alloc_native(md);
1116 /* descriptor_pool_get_parsed_descriptors **************************************
1118 Return a pointer to the block of parsed descriptors
1121 pool.............the descriptor_pool
1124 *size............if size is non-NULL, this is set to the size of the
1125 parsed descriptor block (in u1)
1128 a pointer to the block of parsed descriptors
1131 descriptor_pool_alloc_parsed_descriptors must be called (once)
1132 before this function is used.
1134 *******************************************************************************/
1137 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1140 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1143 *size = pool->descriptorsize;
1145 return pool->descriptors;
1149 /* descriptor_pool_get_sizes ***************************************************
1151 Get the sizes of the class reference table and the parsed descriptors
1154 pool.............the descriptor_pool
1157 *classrefsize....set to size of the class reference table
1158 *descsize........set to size of the parsed descriptors
1161 This function may only be called after both
1162 descriptor_pool_create_classrefs, and
1163 descriptor_pool_alloc_parsed_descriptors
1166 *******************************************************************************/
1169 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1172 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1173 assert(pool->classrefs);
1174 assert(classrefsize);
1177 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1178 *descsize = pool->descriptorsize;
1182 /****************************************************************************/
1184 /****************************************************************************/
1187 /* descriptor_debug_print_typedesc *********************************************
1189 Print the given typedesc to the given stream
1192 file.............stream to print to
1193 d................the parsed descriptor
1195 *******************************************************************************/
1198 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1203 fprintf(file,"(typedesc *)NULL");
1207 if (d->type == TYPE_ADR) {
1209 utf_fprint_printable_ascii(file,d->classref->name);
1211 fprintf(file,"<class=NULL>");
1214 switch (d->primitivetype) {
1215 case PRIMITIVETYPE_INT : ch='I'; break;
1216 case PRIMITIVETYPE_CHAR : ch='C'; break;
1217 case PRIMITIVETYPE_BYTE : ch='B'; break;
1218 case PRIMITIVETYPE_SHORT : ch='S'; break;
1219 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1220 case PRIMITIVETYPE_LONG : ch='J'; break;
1221 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1222 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1223 case PRIMITIVETYPE_VOID : ch='V'; break;
1229 fprintf(file,"[%d]",d->arraydim);
1232 /* descriptor_debug_print_paramdesc ********************************************
1234 Print the given paramdesc to the given stream
1237 file.............stream to print to
1238 d................the parameter descriptor
1240 *******************************************************************************/
1243 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1246 fprintf(file,"(paramdesc *)NULL");
1251 fprintf(file,"<m%d>",d->regoff);
1254 fprintf(file,"<r%d>",d->regoff);
1258 /* descriptor_debug_print_methoddesc *******************************************
1260 Print the given methoddesc to the given stream
1263 file.............stream to print to
1264 d................the parsed descriptor
1266 *******************************************************************************/
1269 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1274 fprintf(file,"(methoddesc *)NULL");
1279 for (i=0; i<d->paramcount; ++i) {
1282 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1284 descriptor_debug_print_paramdesc(file,d->params + i);
1287 if (d->params == METHODDESC_NOPARAMS)
1288 fputs("<NOPARAMS>",file);
1290 descriptor_debug_print_typedesc(file,&(d->returntype));
1293 /* descriptor_pool_debug_dump **************************************************
1295 Print the state of the descriptor_pool to the given stream
1298 pool.............the descriptor_pool
1299 file.............stream to print to
1301 *******************************************************************************/
1304 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1311 fprintf(file,"======[descriptor_pool for ");
1312 utf_fprint_printable_ascii(file,pool->referer->name);
1313 fprintf(file,"]======\n");
1315 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1316 fprintf(file,"methodcount: %d\n",pool->methodcount);
1317 fprintf(file,"paramcount: %d\n",pool->paramcount);
1318 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1319 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1320 fprintf(file,"classrefsize: %d bytes\n",
1321 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1323 fprintf(file,"class references:\n");
1324 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1325 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1327 fprintf(file," %4d: ",c->index);
1328 utf_fprint_printable_ascii(file,c->name);
1334 fprintf(file,"hashed descriptors:\n");
1335 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1336 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1338 fprintf(file," %p: ",c->parseddesc.any);
1339 utf_fprint_printable_ascii(file,c->desc);
1345 fprintf(file,"descriptors:\n");
1346 if (pool->descriptors) {
1347 pos = pool->descriptors;
1348 size = pool->descriptors_next - pool->descriptors;
1349 fprintf(file," size: %d bytes\n",size);
1351 if (pool->descriptor_kind) {
1352 kind = pool->descriptor_kind;
1354 while (pos < (pool->descriptors + size)) {
1355 fprintf(file," %p: ",pos);
1358 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1359 pos += sizeof(typedesc);
1362 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1363 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1364 pos += sizeof(methoddesc) - sizeof(typedesc);
1367 fprintf(file,"INVALID KIND");
1373 while (size >= sizeof(void*)) {
1374 fprintf(file," %p\n",*((void**)pos));
1375 pos += sizeof(void*);
1376 size -= sizeof(void*);
1381 fprintf(file,"==========================================================\n");
1383 #endif /* !defined(NDEBUG) */
1386 * These are local overrides for various environment variables in Emacs.
1387 * Please do not remove this and leave it at the end of the file, where
1388 * Emacs will automagically detect them.
1389 * ---------------------------------------------------------------------
1392 * indent-tabs-mode: t
1396 * vim:noexpandtab:sw=4:ts=4: