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.hpp"
36 #include "vm/descriptor.hpp"
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 #if defined(__cplusplus)
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 int descriptor_to_basic_type(utf *descriptor)
150 assert(descriptor->blength >= 1);
152 switch (descriptor->text[0]) {
174 vm_abort("descriptor_to_basic_type: invalid type %c",
175 descriptor->text[0]);
178 /* keep the compiler happy */
184 /* descriptor_typesize *********************************************************
186 Return the size in bytes needed for the given type.
189 td..............typedesc describing the type
194 *******************************************************************************/
196 int descriptor_typesize(typedesc *td)
210 return SIZEOF_VOID_P;
213 vm_abort("descriptor_typesize: invalid type %d", td->type);
216 /* keep the compiler happy */
222 /* name_from_descriptor ********************************************************
224 Return the class name indicated by the given descriptor
225 (Internally used helper function)
228 c................class containing the descriptor
229 utf_ptr..........first character of descriptor
230 end_ptr..........first character after the end of the string
231 mode.............a combination (binary or) of the following flags:
233 (Flags marked with * are the default settings.)
235 How to handle "V" descriptors:
237 * DESCRIPTOR_VOID.....handle it like other primitive types
238 DESCRIPTOR_NOVOID...treat it as an error
240 How to deal with extra characters after the end of the
243 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
244 DESCRIPTOR_CHECKEND.....treat them as an error
247 *next............if non-NULL, *next is set to the first character after
248 the descriptor. (Undefined if an error occurs.)
249 *name............set to the utf name of the class
252 true.............descriptor parsed successfully
253 false............an exception has been thrown
255 *******************************************************************************/
257 #define DESCRIPTOR_VOID 0 /* default */
258 #define DESCRIPTOR_NOVOID 0x0040
259 #define DESCRIPTOR_NOCHECKEND 0 /* default */
260 #define DESCRIPTOR_CHECKEND 0x1000
263 name_from_descriptor(classinfo *c,
264 char *utf_ptr, char *end_ptr,
265 char **next, int mode, utf **name)
267 char *start = utf_ptr;
276 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
278 if (mode & DESCRIPTOR_CHECKEND)
279 error |= (utf_ptr != end_ptr);
282 if (next) *next = utf_ptr;
286 if (mode & DESCRIPTOR_NOVOID)
304 *name = utf_new(start, utf_ptr - start);
309 exceptions_throw_classformaterror(c, "Invalid descriptor");
314 /* descriptor_to_typedesc ******************************************************
316 Parse the given type descriptor and fill a typedesc struct
317 (Internally used helper function)
320 pool.............the descriptor pool
321 utf_ptr..........points to first character of type descriptor
322 end_pos..........points after last character of the whole descriptor
325 *next............set to next character after type descriptor
326 *d...............filled with parsed information
329 true.............parsing succeeded
330 false............an exception has been thrown
332 *******************************************************************************/
335 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
336 char **next, typedesc *td)
340 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
344 /* a reference type */
346 td->primitivetype = TYPE_ADR;
348 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
350 td->classref = descriptor_pool_lookup_classref(pool, name);
353 /* a primitive type */
356 td->primitivetype = PRIMITIVETYPE_BYTE;
360 td->primitivetype = PRIMITIVETYPE_CHAR;
364 td->primitivetype = PRIMITIVETYPE_SHORT;
368 td->primitivetype = PRIMITIVETYPE_BOOLEAN;
372 td->primitivetype = PRIMITIVETYPE_INT;
376 td->primitivetype = PRIMITIVETYPE_DOUBLE;
380 td->primitivetype = PRIMITIVETYPE_FLOAT;
384 td->primitivetype = PRIMITIVETYPE_LONG;
388 td->primitivetype = PRIMITIVETYPE_VOID;
389 td->type = TYPE_VOID;
403 /* descriptor_pool_new *********************************************************
405 Allocate a new descriptor_pool
408 referer..........class for which to create the pool
411 a pointer to the new descriptor_pool
413 *******************************************************************************/
416 descriptor_pool_new(classinfo *referer)
418 descriptor_pool *pool;
422 pool = (descriptor_pool*) DumpMemory::allocate(sizeof(descriptor_pool));
425 pool->referer = referer;
426 pool->fieldcount = 0;
427 pool->methodcount = 0;
428 pool->paramcount = 0;
429 pool->descriptorsize = 0;
430 pool->descriptors = NULL;
431 pool->descriptors_next = NULL;
432 pool->classrefs = NULL;
433 pool->descriptor_kind = NULL;
434 pool->descriptor_kind_next = NULL;
436 hashsize = CLASSREFHASH_INIT_SIZE;
437 pool->classrefhash.size = hashsize;
438 pool->classrefhash.entries = 0;
439 pool->classrefhash.ptr = (void **) DumpMemory::allocate(sizeof(void*) * hashsize);
440 for (slot=0; slot<hashsize; ++slot)
441 pool->classrefhash.ptr[slot] = NULL;
443 hashsize = DESCRIPTORHASH_INIT_SIZE;
444 pool->descriptorhash.size = hashsize;
445 pool->descriptorhash.entries = 0;
446 pool->descriptorhash.ptr = (void**) DumpMemory::allocate(sizeof(void*) * hashsize);
447 for (slot=0; slot<hashsize; ++slot)
448 pool->descriptorhash.ptr[slot] = NULL;
454 /* descriptor_pool_add_class ***************************************************
456 Add the given class reference to the pool
459 pool.............the descriptor_pool
460 name.............the class reference to add
463 true.............reference has been added
464 false............an exception has been thrown
466 *******************************************************************************/
469 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
472 classref_hash_entry *c;
477 #ifdef DESCRIPTOR_VERBOSE
478 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
479 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
482 /* find a place in the hashtable */
484 key = utf_hashkey(name->text, name->blength);
485 slot = key & (pool->classrefhash.size - 1);
486 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
490 return true; /* already stored */
494 /* check if the name is a valid classname */
496 if (!is_valid_name(name->text,UTF_END(name))) {
497 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
498 return false; /* exception */
501 /* XXX check maximum array dimension */
503 c = (classref_hash_entry*) DumpMemory::allocate(sizeof(classref_hash_entry));
505 c->index = pool->classrefhash.entries++;
506 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
507 pool->classrefhash.ptr[slot] = c;
513 /* descriptor_pool_add *********************************************************
515 Check the given descriptor and add it to the pool
518 pool.............the descriptor_pool
519 desc.............the descriptor to add. Maybe a field or method desc.
522 *paramslots......if non-NULL, set to the number of parameters.
523 LONG and DOUBLE are counted twice
526 true.............descriptor has been added
527 false............an exception has been thrown
529 *******************************************************************************/
532 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
535 descriptor_hash_entry *d;
541 #ifdef DESCRIPTOR_VERBOSE
542 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
543 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
549 /* find a place in the hashtable */
551 key = utf_hashkey(desc->text, desc->blength);
552 slot = key & (pool->descriptorhash.size - 1);
553 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
555 /* Save all method descriptors in the hashtable, since the parsed */
556 /* descriptor may vary between differenf methods (static vs. non-static). */
558 utf_ptr = desc->text;
560 if (*utf_ptr != '(') {
562 if (d->desc == desc) {
564 *paramslots = d->paramslots;
565 return true; /* already stored */
571 /* add the descriptor to the pool */
573 d = (descriptor_hash_entry*) DumpMemory::allocate(sizeof(descriptor_hash_entry));
575 d->parseddesc.any = NULL;
576 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
577 pool->descriptorhash.ptr[slot] = d;
579 /* now check the descriptor */
581 end_pos = UTF_END(desc);
583 if (*utf_ptr == '(') {
584 /* a method descriptor */
589 /* check arguments */
591 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
594 /* We cannot count the `this' argument here because
595 * we don't know if the method is static. */
597 if (*utf_ptr == 'J' || *utf_ptr == 'D')
602 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
603 DESCRIPTOR_NOVOID, &name))
607 if (!descriptor_pool_add_class(pool, name))
611 if (utf_ptr == end_pos) {
612 exceptions_throw_classformaterror(pool->referer,
613 "Missing ')' in method descriptor");
617 utf_ptr++; /* skip ')' */
619 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
620 DESCRIPTOR_CHECKEND, &name))
624 if (!descriptor_pool_add_class(pool,name))
627 if (argcount > 255) {
628 exceptions_throw_classformaterror(pool->referer,
629 "Too many arguments in signature");
634 /* a field descriptor */
638 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
639 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
644 if (!descriptor_pool_add_class(pool,name))
648 d->paramslots = argcount;
651 *paramslots = argcount;
657 /* descriptor_pool_create_classrefs ********************************************
659 Create a table containing all the classrefs which were added to the pool
662 pool.............the descriptor_pool
665 *count...........if count is non-NULL, this is set to the number
666 of classrefs in the table
669 a pointer to the constant_classref table
671 *******************************************************************************/
674 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
678 classref_hash_entry *c;
679 constant_classref *ref;
683 nclasses = pool->classrefhash.entries;
684 pool->classrefs = MNEW(constant_classref,nclasses);
686 /* fill the constant_classref structs */
688 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
689 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
691 ref = pool->classrefs + c->index;
692 CLASSREF_INIT(*ref, pool->referer, c->name);
700 return pool->classrefs;
704 /* descriptor_pool_lookup_classref *********************************************
706 Return the constant_classref for the given class name
709 pool.............the descriptor_pool
710 classname........name of the class to look up
713 a pointer to the constant_classref, or
714 NULL if an exception has been thrown
716 *******************************************************************************/
719 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
722 classref_hash_entry *c;
725 assert(pool->classrefs);
728 key = utf_hashkey(classname->text, classname->blength);
729 slot = key & (pool->classrefhash.size - 1);
730 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
733 if (c->name == classname)
734 return pool->classrefs + c->index;
738 exceptions_throw_internalerror("Class reference not found in descriptor pool");
743 /* descriptor_pool_alloc_parsed_descriptors ************************************
745 Allocate space for the parsed descriptors
748 pool.............the descriptor_pool
751 This function must be called after all descriptors have been added
752 with descriptor_pool_add.
754 *******************************************************************************/
757 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
763 /* TWISTI: paramcount + 1: we don't know if the method is static or */
764 /* not, i have no better solution yet. */
767 pool->fieldcount * sizeof(typedesc) +
768 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
769 pool->paramcount * sizeof(typedesc) +
770 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
772 pool->descriptorsize = size;
774 pool->descriptors = MNEW(u1, size);
775 pool->descriptors_next = pool->descriptors;
778 size = pool->fieldcount + pool->methodcount;
780 pool->descriptor_kind = (u1*) DumpMemory::allocate(sizeof(u1) * size);
781 pool->descriptor_kind_next = pool->descriptor_kind;
786 /* descriptor_pool_parse_field_descriptor **************************************
788 Parse the given field descriptor
791 pool.............the descriptor_pool
792 desc.............the field descriptor
795 a pointer to the parsed field descriptor, or
796 NULL if an exception has been thrown
799 descriptor_pool_alloc_parsed_descriptors must be called (once)
800 before this function is used.
802 *******************************************************************************/
805 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
808 descriptor_hash_entry *d;
812 assert(pool->descriptors);
813 assert(pool->descriptors_next);
815 /* lookup the descriptor in the hashtable */
817 key = utf_hashkey(desc->text, desc->blength);
818 slot = key & (pool->descriptorhash.size - 1);
819 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
822 if (d->desc == desc) {
824 if (d->parseddesc.fd)
825 return d->parseddesc.fd;
833 if (desc->text[0] == '(') {
834 exceptions_throw_classformaterror(pool->referer,
835 "Method descriptor used in field reference");
839 td = (typedesc *) pool->descriptors_next;
840 pool->descriptors_next += sizeof(typedesc);
842 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
845 *(pool->descriptor_kind_next++) = 'f';
847 d->parseddesc.fd = td;
853 /* descriptor_pool_parse_method_descriptor *************************************
855 Parse the given method descriptor
858 pool.............the descriptor_pool
859 desc.............the method descriptor
860 mflags...........the method flags
861 thisclass........classref to the class containing the method.
862 This is ignored if mflags contains ACC_STATIC.
863 The classref is stored for inserting the 'this' argument.
866 a pointer to the parsed method descriptor, or
867 NULL if an exception has been thrown
870 descriptor_pool_alloc_parsed_descriptors must be called
871 (once) before this function is used.
873 *******************************************************************************/
876 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
877 s4 mflags,constant_classref *thisclass)
880 descriptor_hash_entry *d;
888 #ifdef DESCRIPTOR_VERBOSE
889 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
890 (void*)pool,(int)mflags,(void*)thisclass);
891 utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
895 assert(pool->descriptors);
896 assert(pool->descriptors_next);
898 /* check that it is a method descriptor */
900 if (desc->text[0] != '(') {
901 exceptions_throw_classformaterror(pool->referer,
902 "Field descriptor used in method reference");
906 /* lookup the descriptor in the hashtable */
908 key = utf_hashkey(desc->text, desc->blength);
909 slot = key & (pool->descriptorhash.size - 1);
910 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
912 /* find an un-parsed descriptor */
916 if (!d->parseddesc.md)
923 md = (methoddesc *) pool->descriptors_next;
924 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
926 utf_ptr = desc->text + 1; /* skip '(' */
927 end_pos = UTF_END(desc);
931 /* count the `this' pointer */
933 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
935 td->primitivetype = TYPE_ADR;
937 td->classref = thisclass;
940 pool->descriptors_next += sizeof(typedesc);
945 while (*utf_ptr != ')') {
946 /* parse a parameter type */
948 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
951 if (IS_2_WORD_TYPE(td->type))
955 pool->descriptors_next += sizeof(typedesc);
959 utf_ptr++; /* skip ')' */
961 /* Skip possible `this' pointer in paramtypes array to allow a possible */
962 /* memory move later in parse. */
963 /* We store the thisclass reference, so we can later correctly fill in */
964 /* the parameter slot of the 'this' argument. */
966 if (mflags == ACC_UNDEF) {
967 td->classref = thisclass;
969 pool->descriptors_next += sizeof(typedesc);
972 /* parse return type */
974 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
978 md->paramcount = paramcount;
979 md->paramslots = paramslots;
981 /* If mflags != ACC_UNDEF we parse a real loaded method, so do
982 param prealloc. Otherwise we do this in stack analysis. */
984 if (mflags != ACC_UNDEF) {
985 if (md->paramcount > 0) {
986 /* allocate memory for params */
988 md->params = MNEW(paramdesc, md->paramcount);
991 md->params = METHODDESC_NOPARAMS;
994 /* fill the paramdesc */
995 /* md_param_alloc has to be called if md->paramcount == 0,
996 too, so it can make the reservation for the Linkage Area,
997 Return Register... */
999 #if defined(ENABLE_JIT)
1000 # if defined(ENABLE_INTRP)
1004 /* As builtin-functions are native functions, we have
1005 to pre-allocate for the native ABI. */
1007 if (mflags & ACC_METHOD_BUILTIN)
1008 md_param_alloc_native(md);
1015 /* params will be allocated later by
1016 descriptor_params_from_paramtypes if necessary */
1021 *(pool->descriptor_kind_next++) = 'm';
1023 d->parseddesc.md = md;
1028 /* descriptor_params_from_paramtypes *******************************************
1030 Create the paramdescs for a method descriptor. This function is called
1031 when we know whether the method is static or not. This function may only
1032 be called once for each methoddesc, and only if md->params == NULL.
1035 md...............the parsed method descriptor
1036 md->params MUST be NULL.
1037 mflags...........the ACC_* access flags of the method. Only the
1038 ACC_STATIC bit is checked.
1039 The value ACC_UNDEF is NOT allowed.
1042 true.............the paramdescs were created successfully
1043 false............an exception has been thrown
1048 *******************************************************************************/
1050 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1055 assert(md->params == NULL);
1056 assert(mflags != ACC_UNDEF);
1058 td = md->paramtypes;
1060 /* check for `this' pointer */
1062 if (!(mflags & ACC_STATIC)) {
1063 constant_classref *thisclass;
1065 /* fetch class reference from reserved param slot */
1066 thisclass = td[md->paramcount].classref;
1069 if (md->paramcount > 0) {
1070 /* shift param types by 1 argument */
1071 MMOVE(td + 1, td, typedesc, md->paramcount);
1074 /* fill in first argument `this' */
1076 td->type = TYPE_ADR;
1077 td->primitivetype = TYPE_ADR;
1079 td->classref = thisclass;
1085 /* if the method has params, process them */
1087 if (md->paramcount > 0) {
1088 /* allocate memory for params */
1090 md->params = MNEW(paramdesc, md->paramcount);
1093 md->params = METHODDESC_NOPARAMS;
1096 /* fill the paramdesc */
1097 /* md_param_alloc has to be called if md->paramcount == 0, too, so
1098 it can make the reservation for the Linkage Area, Return
1101 #if defined(ENABLE_JIT)
1102 # if defined(ENABLE_INTRP)
1106 /* As builtin-functions are native functions, we have to
1107 pre-allocate for the native ABI. */
1109 if (mflags & ACC_METHOD_BUILTIN)
1110 md_param_alloc_native(md);
1120 /* descriptor_pool_get_parsed_descriptors **************************************
1122 Return a pointer to the block of parsed descriptors
1125 pool.............the descriptor_pool
1128 *size............if size is non-NULL, this is set to the size of the
1129 parsed descriptor block (in u1)
1132 a pointer to the block of parsed descriptors
1135 descriptor_pool_alloc_parsed_descriptors must be called (once)
1136 before this function is used.
1138 *******************************************************************************/
1141 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1144 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1147 *size = pool->descriptorsize;
1149 return pool->descriptors;
1153 /* descriptor_pool_get_sizes ***************************************************
1155 Get the sizes of the class reference table and the parsed descriptors
1158 pool.............the descriptor_pool
1161 *classrefsize....set to size of the class reference table
1162 *descsize........set to size of the parsed descriptors
1165 This function may only be called after both
1166 descriptor_pool_create_classrefs, and
1167 descriptor_pool_alloc_parsed_descriptors
1170 *******************************************************************************/
1173 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1176 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1177 assert(pool->classrefs);
1178 assert(classrefsize);
1181 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1182 *descsize = pool->descriptorsize;
1186 /****************************************************************************/
1188 /****************************************************************************/
1191 /* descriptor_debug_print_typedesc *********************************************
1193 Print the given typedesc to the given stream
1196 file.............stream to print to
1197 d................the parsed descriptor
1199 *******************************************************************************/
1202 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1207 fprintf(file,"(typedesc *)NULL");
1211 if (d->type == TYPE_ADR) {
1213 utf_fprint_printable_ascii(file,d->classref->name);
1215 fprintf(file,"<class=NULL>");
1218 switch (d->primitivetype) {
1219 case PRIMITIVETYPE_INT : ch='I'; break;
1220 case PRIMITIVETYPE_CHAR : ch='C'; break;
1221 case PRIMITIVETYPE_BYTE : ch='B'; break;
1222 case PRIMITIVETYPE_SHORT : ch='S'; break;
1223 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1224 case PRIMITIVETYPE_LONG : ch='J'; break;
1225 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1226 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1227 case PRIMITIVETYPE_VOID : ch='V'; break;
1233 fprintf(file,"[%d]",d->arraydim);
1236 /* descriptor_debug_print_paramdesc ********************************************
1238 Print the given paramdesc to the given stream
1241 file.............stream to print to
1242 d................the parameter descriptor
1244 *******************************************************************************/
1247 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1250 fprintf(file,"(paramdesc *)NULL");
1255 fprintf(file,"<m%d>",d->regoff);
1258 fprintf(file,"<r%d>",d->regoff);
1262 /* descriptor_debug_print_methoddesc *******************************************
1264 Print the given methoddesc to the given stream
1267 file.............stream to print to
1268 d................the parsed descriptor
1270 *******************************************************************************/
1273 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1278 fprintf(file,"(methoddesc *)NULL");
1283 for (i=0; i<d->paramcount; ++i) {
1286 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1288 descriptor_debug_print_paramdesc(file,d->params + i);
1291 if (d->params == METHODDESC_NOPARAMS)
1292 fputs("<NOPARAMS>",file);
1294 descriptor_debug_print_typedesc(file,&(d->returntype));
1297 /* descriptor_pool_debug_dump **************************************************
1299 Print the state of the descriptor_pool to the given stream
1302 pool.............the descriptor_pool
1303 file.............stream to print to
1305 *******************************************************************************/
1308 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1315 fprintf(file,"======[descriptor_pool for ");
1316 utf_fprint_printable_ascii(file,pool->referer->name);
1317 fprintf(file,"]======\n");
1319 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1320 fprintf(file,"methodcount: %d\n",pool->methodcount);
1321 fprintf(file,"paramcount: %d\n",pool->paramcount);
1322 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1323 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1324 fprintf(file,"classrefsize: %d bytes\n",
1325 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1327 fprintf(file,"class references:\n");
1328 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1329 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1331 fprintf(file," %4d: ",c->index);
1332 utf_fprint_printable_ascii(file,c->name);
1338 fprintf(file,"hashed descriptors:\n");
1339 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1340 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1342 fprintf(file," %p: ",c->parseddesc.any);
1343 utf_fprint_printable_ascii(file,c->desc);
1349 fprintf(file,"descriptors:\n");
1350 if (pool->descriptors) {
1351 pos = pool->descriptors;
1352 size = pool->descriptors_next - pool->descriptors;
1353 fprintf(file," size: %d bytes\n",size);
1355 if (pool->descriptor_kind) {
1356 kind = pool->descriptor_kind;
1358 while (pos < (pool->descriptors + size)) {
1359 fprintf(file," %p: ",pos);
1362 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1363 pos += sizeof(typedesc);
1366 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1367 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1368 pos += sizeof(methoddesc) - sizeof(typedesc);
1371 fprintf(file,"INVALID KIND");
1377 while (size >= sizeof(void*)) {
1378 fprintf(file," %p\n",*((void**)pos));
1379 pos += sizeof(void*);
1380 size -= sizeof(void*);
1385 fprintf(file,"==========================================================\n");
1387 #endif /* !defined(NDEBUG) */
1389 #if defined(__cplusplus)
1394 * These are local overrides for various environment variables in Emacs.
1395 * Please do not remove this and leave it at the end of the file, where
1396 * Emacs will automagically detect them.
1397 * ---------------------------------------------------------------------
1400 * indent-tabs-mode: t
1404 * vim:noexpandtab:sw=4:ts=4: