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 7246 2007-01-29 18:49:05Z twisti $
38 #include "mm/memory.h"
40 #include "vm/exceptions.h"
42 #include "vmcore/descriptor.h"
43 #include "vmcore/options.h"
44 #include "vmcore/resolve.h"
47 /* constants (private to descriptor.c) ****************************************/
49 /* initial number of entries for the classrefhash of a descriptor_pool */
50 /* (currently the hash is never grown!) */
51 #define CLASSREFHASH_INIT_SIZE 64
53 /* initial number of entries for the descriptorhash of a descriptor_pool */
54 /* (currently the hash is never grown!) */
55 #define DESCRIPTORHASH_INIT_SIZE 128
57 /* data structures (private to descriptor.c) **********************************/
59 typedef struct classref_hash_entry classref_hash_entry;
60 typedef struct descriptor_hash_entry descriptor_hash_entry;
62 /* entry struct for the classrefhash of descriptor_pool */
63 struct classref_hash_entry {
64 classref_hash_entry *hashlink; /* for hash chaining */
65 utf *name; /* name of the class refered to */
66 u2 index; /* index into classref table */
69 /* entry struct for the descriptorhash of descriptor_pool */
70 struct descriptor_hash_entry {
71 descriptor_hash_entry *hashlink;
73 parseddesc parseddesc;
74 s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
78 /****************************************************************************/
79 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
80 /****************************************************************************/
82 /* SKIP_FIELDDESCRIPTOR:
83 * utf_ptr must point to the first character of a field descriptor.
84 * After the macro call utf_ptr points to the first character after
85 * the field descriptor.
87 * CAUTION: This macro does not check for an unexpected end of the
88 * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
90 #define SKIP_FIELDDESCRIPTOR(utf_ptr) \
91 do { while (*(utf_ptr)=='[') (utf_ptr)++; \
92 if (*(utf_ptr)++=='L') \
93 while(*(utf_ptr)++ != ';') /* skip */; } while(0)
95 /* SKIP_FIELDDESCRIPTOR_SAFE:
96 * utf_ptr must point to the first character of a field descriptor.
97 * After the macro call utf_ptr points to the first character after
98 * the field descriptor.
101 * utf_ptr....points to first char of descriptor
102 * end_ptr....points to first char after the end of the string
103 * errorflag..must be initialized (to false) by the caller!
105 * utf_ptr....points to first char after the descriptor
106 * errorflag..set to true if the string ended unexpectedly
108 #define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
109 do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
110 if ((utf_ptr) == (end_ptr)) \
111 (errorflag) = true; \
113 if (*(utf_ptr)++=='L') { \
114 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
116 if ((utf_ptr)[-1] != ';') \
117 (errorflag) = true; }} while(0)
120 /****************************************************************************/
122 /****************************************************************************/
124 /*#define DESCRIPTOR_VERBOSE*/
126 /****************************************************************************/
128 /****************************************************************************/
130 /* descriptor_to_basic_type ****************************************************
132 Return the basic type to use for a value with this descriptor.
135 utf..............descriptor utf string
141 This function assumes that the descriptor has passed
142 descriptor_pool_add checks and that it does not start with '('.
144 *******************************************************************************/
146 u2 descriptor_to_basic_type(utf *descriptor)
148 assert(descriptor->blength >= 1);
150 switch (descriptor->text[0]) {
155 case 'Z': return TYPE_INT;
156 case 'D': return TYPE_DBL;
157 case 'F': return TYPE_FLT;
158 case 'J': return TYPE_LNG;
160 case '[': return TYPE_ADR;
165 return 0; /* keep the compiler happy */
168 /* descriptor_typesize**** ****************************************************
170 Return the size in bytes needed for the given type.
173 td..............typedesc describing the type
178 *******************************************************************************/
180 u2 descriptor_typesize(typedesc *td)
185 case TYPE_INT: return 4;
186 case TYPE_LNG: return 8;
187 case TYPE_FLT: return 4;
188 case TYPE_DBL: return 8;
189 case TYPE_ADR: return sizeof(voidptr);
194 return 0; /* keep the compiler happy */
197 /* name_from_descriptor ********************************************************
199 Return the class name indicated by the given descriptor
200 (Internally used helper function)
203 c................class containing the descriptor
204 utf_ptr..........first character of descriptor
205 end_ptr..........first character after the end of the string
206 mode.............a combination (binary or) of the following flags:
208 (Flags marked with * are the default settings.)
210 How to handle "V" descriptors:
212 * DESCRIPTOR_VOID.....handle it like other primitive types
213 DESCRIPTOR_NOVOID...treat it as an error
215 How to deal with extra characters after the end of the
218 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
219 DESCRIPTOR_CHECKEND.....treat them as an error
222 *next............if non-NULL, *next is set to the first character after
223 the descriptor. (Undefined if an error occurs.)
224 *name............set to the utf name of the class
227 true.............descriptor parsed successfully
228 false............an exception has been thrown
230 *******************************************************************************/
232 #define DESCRIPTOR_VOID 0 /* default */
233 #define DESCRIPTOR_NOVOID 0x0040
234 #define DESCRIPTOR_NOCHECKEND 0 /* default */
235 #define DESCRIPTOR_CHECKEND 0x1000
238 name_from_descriptor(classinfo *c,
239 char *utf_ptr, char *end_ptr,
240 char **next, int mode, utf **name)
242 char *start = utf_ptr;
251 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
253 if (mode & DESCRIPTOR_CHECKEND)
254 error |= (utf_ptr != end_ptr);
257 if (next) *next = utf_ptr;
261 if (mode & DESCRIPTOR_NOVOID)
279 *name = utf_new(start, utf_ptr - start);
284 exceptions_throw_classformaterror(c, "Invalid descriptor");
289 /* descriptor_to_typedesc ******************************************************
291 Parse the given type descriptor and fill a typedesc struct
292 (Internally used helper function)
295 pool.............the descriptor pool
296 utf_ptr..........points to first character of type descriptor
297 end_pos..........points after last character of the whole descriptor
300 *next............set to next character after type descriptor
301 *d...............filled with parsed information
304 true.............parsing succeeded
305 false............an exception has been thrown
307 *******************************************************************************/
310 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
311 char **next, typedesc *td)
315 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
319 /* a reference type */
321 td->decltype = TYPE_ADR;
323 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
325 td->classref = descriptor_pool_lookup_classref(pool, name);
328 /* a primitive type */
331 td->decltype = PRIMITIVETYPE_BYTE;
335 td->decltype = PRIMITIVETYPE_CHAR;
339 td->decltype = PRIMITIVETYPE_SHORT;
343 td->decltype = PRIMITIVETYPE_BOOLEAN;
347 td->decltype = PRIMITIVETYPE_INT;
351 td->decltype = PRIMITIVETYPE_DOUBLE;
355 td->decltype = PRIMITIVETYPE_FLOAT;
359 td->decltype = PRIMITIVETYPE_LONG;
363 td->decltype = PRIMITIVETYPE_VOID;
364 td->type = TYPE_VOID;
378 /* descriptor_pool_new *********************************************************
380 Allocate a new descriptor_pool
383 referer..........class for which to create the pool
386 a pointer to the new descriptor_pool
388 *******************************************************************************/
391 descriptor_pool_new(classinfo *referer)
393 descriptor_pool *pool;
397 pool = DNEW(descriptor_pool);
400 pool->referer = referer;
401 pool->fieldcount = 0;
402 pool->methodcount = 0;
403 pool->paramcount = 0;
404 pool->descriptorsize = 0;
405 pool->descriptors = NULL;
406 pool->descriptors_next = NULL;
407 pool->classrefs = NULL;
408 pool->descriptor_kind = NULL;
409 pool->descriptor_kind_next = NULL;
411 hashsize = CLASSREFHASH_INIT_SIZE;
412 pool->classrefhash.size = hashsize;
413 pool->classrefhash.entries = 0;
414 pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
415 for (slot=0; slot<hashsize; ++slot)
416 pool->classrefhash.ptr[slot] = NULL;
418 hashsize = DESCRIPTORHASH_INIT_SIZE;
419 pool->descriptorhash.size = hashsize;
420 pool->descriptorhash.entries = 0;
421 pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
422 for (slot=0; slot<hashsize; ++slot)
423 pool->descriptorhash.ptr[slot] = NULL;
429 /* descriptor_pool_add_class ***************************************************
431 Add the given class reference to the pool
434 pool.............the descriptor_pool
435 name.............the class reference to add
438 true.............reference has been added
439 false............an exception has been thrown
441 *******************************************************************************/
444 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
447 classref_hash_entry *c;
452 #ifdef DESCRIPTOR_VERBOSE
453 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
454 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
457 /* find a place in the hashtable */
459 key = utf_hashkey(name->text, name->blength);
460 slot = key & (pool->classrefhash.size - 1);
461 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
465 return true; /* already stored */
469 /* check if the name is a valid classname */
471 if (!is_valid_name(name->text,UTF_END(name))) {
472 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
473 return false; /* exception */
476 /* XXX check maximum array dimension */
478 c = DNEW(classref_hash_entry);
480 c->index = pool->classrefhash.entries++;
481 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
482 pool->classrefhash.ptr[slot] = c;
488 /* descriptor_pool_add *********************************************************
490 Check the given descriptor and add it to the pool
493 pool.............the descriptor_pool
494 desc.............the descriptor to add. Maybe a field or method desc.
497 *paramslots......if non-NULL, set to the number of parameters.
498 LONG and DOUBLE are counted twice
501 true.............descriptor has been added
502 false............an exception has been thrown
504 *******************************************************************************/
507 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
510 descriptor_hash_entry *d;
516 #ifdef DESCRIPTOR_VERBOSE
517 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
518 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
524 /* find a place in the hashtable */
526 key = utf_hashkey(desc->text, desc->blength);
527 slot = key & (pool->descriptorhash.size - 1);
528 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
530 /* Save all method descriptors in the hashtable, since the parsed */
531 /* descriptor may vary between differenf methods (static vs. non-static). */
533 utf_ptr = desc->text;
535 if (*utf_ptr != '(') {
537 if (d->desc == desc) {
539 *paramslots = d->paramslots;
540 return true; /* already stored */
546 /* add the descriptor to the pool */
548 d = DNEW(descriptor_hash_entry);
550 d->parseddesc.any = NULL;
551 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
552 pool->descriptorhash.ptr[slot] = d;
554 /* now check the descriptor */
556 end_pos = UTF_END(desc);
558 if (*utf_ptr == '(') {
559 /* a method descriptor */
564 /* check arguments */
566 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
569 /* We cannot count the `this' argument here because
570 * we don't know if the method is static. */
572 if (*utf_ptr == 'J' || *utf_ptr == 'D')
577 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
578 DESCRIPTOR_NOVOID, &name))
582 if (!descriptor_pool_add_class(pool, name))
586 if (utf_ptr == end_pos) {
587 exceptions_throw_classformaterror(pool->referer,
588 "Missing ')' in method descriptor");
592 utf_ptr++; /* skip ')' */
594 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
595 DESCRIPTOR_CHECKEND, &name))
599 if (!descriptor_pool_add_class(pool,name))
602 if (argcount > 255) {
603 exceptions_throw_classformaterror(pool->referer,
604 "Too many arguments in signature");
609 /* a field descriptor */
613 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
614 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
619 if (!descriptor_pool_add_class(pool,name))
623 d->paramslots = argcount;
626 *paramslots = argcount;
632 /* descriptor_pool_create_classrefs ********************************************
634 Create a table containing all the classrefs which were added to the pool
637 pool.............the descriptor_pool
640 *count...........if count is non-NULL, this is set to the number
641 of classrefs in the table
644 a pointer to the constant_classref table
646 *******************************************************************************/
649 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
653 classref_hash_entry *c;
654 constant_classref *ref;
658 nclasses = pool->classrefhash.entries;
659 pool->classrefs = MNEW(constant_classref,nclasses);
661 /* fill the constant_classref structs */
663 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
664 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
666 ref = pool->classrefs + c->index;
667 CLASSREF_INIT(*ref, pool->referer, c->name);
675 return pool->classrefs;
679 /* descriptor_pool_lookup_classref *********************************************
681 Return the constant_classref for the given class name
684 pool.............the descriptor_pool
685 classname........name of the class to look up
688 a pointer to the constant_classref, or
689 NULL if an exception has been thrown
691 *******************************************************************************/
694 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
697 classref_hash_entry *c;
700 assert(pool->classrefs);
703 key = utf_hashkey(classname->text, classname->blength);
704 slot = key & (pool->classrefhash.size - 1);
705 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
708 if (c->name == classname)
709 return pool->classrefs + c->index;
713 exceptions_throw_internalerror("Class reference not found in descriptor pool");
718 /* descriptor_pool_alloc_parsed_descriptors ************************************
720 Allocate space for the parsed descriptors
723 pool.............the descriptor_pool
726 This function must be called after all descriptors have been added
727 with descriptor_pool_add.
729 *******************************************************************************/
732 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
738 /* TWISTI: paramcount + 1: we don't know if the method is static or */
739 /* not, i have no better solution yet. */
742 pool->fieldcount * sizeof(typedesc) +
743 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
744 pool->paramcount * sizeof(typedesc) +
745 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
747 pool->descriptorsize = size;
749 pool->descriptors = MNEW(u1, size);
750 pool->descriptors_next = pool->descriptors;
753 size = pool->fieldcount + pool->methodcount;
755 pool->descriptor_kind = DMNEW(u1, size);
756 pool->descriptor_kind_next = pool->descriptor_kind;
761 /* descriptor_pool_parse_field_descriptor **************************************
763 Parse the given field descriptor
766 pool.............the descriptor_pool
767 desc.............the field descriptor
770 a pointer to the parsed field descriptor, or
771 NULL if an exception has been thrown
774 descriptor_pool_alloc_parsed_descriptors must be called (once)
775 before this function is used.
777 *******************************************************************************/
780 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
783 descriptor_hash_entry *d;
787 assert(pool->descriptors);
788 assert(pool->descriptors_next);
790 /* lookup the descriptor in the hashtable */
792 key = utf_hashkey(desc->text, desc->blength);
793 slot = key & (pool->descriptorhash.size - 1);
794 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
797 if (d->desc == desc) {
799 if (d->parseddesc.fd)
800 return d->parseddesc.fd;
808 if (desc->text[0] == '(') {
809 exceptions_throw_classformaterror(pool->referer,
810 "Method descriptor used in field reference");
814 td = (typedesc *) pool->descriptors_next;
815 pool->descriptors_next += sizeof(typedesc);
817 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
820 *(pool->descriptor_kind_next++) = 'f';
822 d->parseddesc.fd = td;
828 /* descriptor_pool_parse_method_descriptor *************************************
830 Parse the given method descriptor
833 pool.............the descriptor_pool
834 desc.............the method descriptor
835 mflags...........the method flags
836 thisclass........classref to the class containing the method.
837 This is ignored if mflags contains ACC_STATIC.
838 The classref is stored for inserting the 'this' argument.
841 a pointer to the parsed method descriptor, or
842 NULL if an exception has been thrown
845 descriptor_pool_alloc_parsed_descriptors must be called
846 (once) before this function is used.
848 *******************************************************************************/
851 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
852 s4 mflags,constant_classref *thisclass)
855 descriptor_hash_entry *d;
863 #ifdef DESCRIPTOR_VERBOSE
864 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
865 (void*)pool,(int)mflags,(void*)thisclass);
866 utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
870 assert(pool->descriptors);
871 assert(pool->descriptors_next);
873 /* check that it is a method descriptor */
875 if (desc->text[0] != '(') {
876 exceptions_throw_classformaterror(pool->referer,
877 "Field descriptor used in method reference");
881 /* lookup the descriptor in the hashtable */
883 key = utf_hashkey(desc->text, desc->blength);
884 slot = key & (pool->descriptorhash.size - 1);
885 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
887 /* find an un-parsed descriptor */
891 if (!d->parseddesc.md)
898 md = (methoddesc *) pool->descriptors_next;
899 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
901 utf_ptr = desc->text + 1; /* skip '(' */
902 end_pos = UTF_END(desc);
906 /* count the `this' pointer */
908 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
910 td->decltype = TYPE_ADR;
912 td->classref = thisclass;
915 pool->descriptors_next += sizeof(typedesc);
920 while (*utf_ptr != ')') {
921 /* parse a parameter type */
923 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
926 if (IS_2_WORD_TYPE(td->type))
930 pool->descriptors_next += sizeof(typedesc);
934 utf_ptr++; /* skip ')' */
936 /* Skip possible `this' pointer in paramtypes array to allow a possible */
937 /* memory move later in parse. */
938 /* We store the thisclass reference, so we can later correctly fill in */
939 /* the parameter slot of the 'this' argument. */
941 if (mflags == ACC_UNDEF) {
942 td->classref = thisclass;
944 pool->descriptors_next += sizeof(typedesc);
947 /* parse return type */
949 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
953 md->paramcount = paramcount;
954 md->paramslots = paramslots;
956 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
957 /* Otherwise we do this in stack analysis. */
959 if (mflags != ACC_UNDEF) {
960 if (md->paramcount > 0) {
961 /* allocate memory for params */
963 md->params = MNEW(paramdesc, md->paramcount);
966 md->params = METHODDESC_NOPARAMS;
969 /* fill the paramdesc */
970 /* md_param_alloc has to be called if md->paramcount == 0,
971 too, so it can make the reservation for the Linkage Area,
972 Return Register... */
974 #if defined(ENABLE_JIT)
975 # if defined(ENABLE_INTRP)
982 /* params will be allocated later by
983 descriptor_params_from_paramtypes if necessary */
988 *(pool->descriptor_kind_next++) = 'm';
990 d->parseddesc.md = md;
995 /* descriptor_params_from_paramtypes *******************************************
997 Create the paramdescs for a method descriptor. This function is called
998 when we know whether the method is static or not. This function may only
999 be called once for each methoddesc, and only if md->params == NULL.
1002 md...............the parsed method descriptor
1003 md->params MUST be NULL.
1004 mflags...........the ACC_* access flags of the method. Only the
1005 ACC_STATIC bit is checked.
1006 The value ACC_UNDEF is NOT allowed.
1009 true.............the paramdescs were created successfully
1010 false............an exception has been thrown
1015 *******************************************************************************/
1017 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1022 assert(md->params == NULL);
1023 assert(mflags != ACC_UNDEF);
1025 td = md->paramtypes;
1027 /* check for `this' pointer */
1029 if (!(mflags & ACC_STATIC)) {
1030 constant_classref *thisclass;
1032 /* fetch class reference from reserved param slot */
1033 thisclass = td[md->paramcount].classref;
1036 if (md->paramcount > 0) {
1037 /* shift param types by 1 argument */
1038 MMOVE(td + 1, td, typedesc, md->paramcount);
1041 /* fill in first argument `this' */
1043 td->type = TYPE_ADR;
1044 td->decltype = TYPE_ADR;
1046 td->classref = thisclass;
1052 /* if the method has params, process them */
1054 if (md->paramcount > 0) {
1055 /* allocate memory for params */
1057 md->params = MNEW(paramdesc, md->paramcount);
1060 md->params = METHODDESC_NOPARAMS;
1063 /* fill the paramdesc */
1064 /* md_param_alloc has to be called if md->paramcount == 0, too, so
1065 it can make the reservation for the Linkage Area, Return
1068 #if defined(ENABLE_JIT)
1069 # if defined(ENABLE_INTRP)
1079 /* descriptor_pool_get_parsed_descriptors **************************************
1081 Return a pointer to the block of parsed descriptors
1084 pool.............the descriptor_pool
1087 *size............if size is non-NULL, this is set to the size of the
1088 parsed descriptor block (in u1)
1091 a pointer to the block of parsed descriptors
1094 descriptor_pool_alloc_parsed_descriptors must be called (once)
1095 before this function is used.
1097 *******************************************************************************/
1100 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1103 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1106 *size = pool->descriptorsize;
1108 return pool->descriptors;
1112 /* descriptor_pool_get_sizes ***************************************************
1114 Get the sizes of the class reference table and the parsed descriptors
1117 pool.............the descriptor_pool
1120 *classrefsize....set to size of the class reference table
1121 *descsize........set to size of the parsed descriptors
1124 This function may only be called after both
1125 descriptor_pool_create_classrefs, and
1126 descriptor_pool_alloc_parsed_descriptors
1129 *******************************************************************************/
1132 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1135 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1136 assert(pool->classrefs);
1137 assert(classrefsize);
1140 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1141 *descsize = pool->descriptorsize;
1145 /****************************************************************************/
1147 /****************************************************************************/
1150 /* descriptor_debug_print_typedesc *********************************************
1152 Print the given typedesc to the given stream
1155 file.............stream to print to
1156 d................the parsed descriptor
1158 *******************************************************************************/
1161 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1166 fprintf(file,"(typedesc *)NULL");
1170 if (d->type == TYPE_ADR) {
1172 utf_fprint_printable_ascii(file,d->classref->name);
1174 fprintf(file,"<class=NULL>");
1177 switch (d->decltype) {
1178 case PRIMITIVETYPE_INT : ch='I'; break;
1179 case PRIMITIVETYPE_CHAR : ch='C'; break;
1180 case PRIMITIVETYPE_BYTE : ch='B'; break;
1181 case PRIMITIVETYPE_SHORT : ch='S'; break;
1182 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1183 case PRIMITIVETYPE_LONG : ch='J'; break;
1184 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1185 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1186 case PRIMITIVETYPE_VOID : ch='V'; break;
1192 fprintf(file,"[%d]",d->arraydim);
1195 /* descriptor_debug_print_paramdesc ********************************************
1197 Print the given paramdesc to the given stream
1200 file.............stream to print to
1201 d................the parameter descriptor
1203 *******************************************************************************/
1206 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1209 fprintf(file,"(paramdesc *)NULL");
1214 fprintf(file,"<m%d>",d->regoff);
1217 fprintf(file,"<r%d>",d->regoff);
1221 /* descriptor_debug_print_methoddesc *******************************************
1223 Print the given methoddesc to the given stream
1226 file.............stream to print to
1227 d................the parsed descriptor
1229 *******************************************************************************/
1232 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1237 fprintf(file,"(methoddesc *)NULL");
1242 for (i=0; i<d->paramcount; ++i) {
1245 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1247 descriptor_debug_print_paramdesc(file,d->params + i);
1250 if (d->params == METHODDESC_NOPARAMS)
1251 fputs("<NOPARAMS>",file);
1253 descriptor_debug_print_typedesc(file,&(d->returntype));
1256 /* descriptor_pool_debug_dump **************************************************
1258 Print the state of the descriptor_pool to the given stream
1261 pool.............the descriptor_pool
1262 file.............stream to print to
1264 *******************************************************************************/
1267 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1274 fprintf(file,"======[descriptor_pool for ");
1275 utf_fprint_printable_ascii(file,pool->referer->name);
1276 fprintf(file,"]======\n");
1278 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1279 fprintf(file,"methodcount: %d\n",pool->methodcount);
1280 fprintf(file,"paramcount: %d\n",pool->paramcount);
1281 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1282 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1283 fprintf(file,"classrefsize: %d bytes\n",
1284 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1286 fprintf(file,"class references:\n");
1287 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1288 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1290 fprintf(file," %4d: ",c->index);
1291 utf_fprint_printable_ascii(file,c->name);
1297 fprintf(file,"hashed descriptors:\n");
1298 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1299 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1301 fprintf(file," %p: ",c->parseddesc.any);
1302 utf_fprint_printable_ascii(file,c->desc);
1308 fprintf(file,"descriptors:\n");
1309 if (pool->descriptors) {
1310 pos = pool->descriptors;
1311 size = pool->descriptors_next - pool->descriptors;
1312 fprintf(file," size: %d bytes\n",size);
1314 if (pool->descriptor_kind) {
1315 kind = pool->descriptor_kind;
1317 while (pos < (pool->descriptors + size)) {
1318 fprintf(file," %p: ",pos);
1321 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1322 pos += sizeof(typedesc);
1325 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1326 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1327 pos += sizeof(methoddesc) - sizeof(typedesc);
1330 fprintf(file,"INVALID KIND");
1336 while (size >= sizeof(voidptr)) {
1337 fprintf(file," %p\n",*((voidptr*)pos));
1338 pos += sizeof(voidptr);
1339 size -= sizeof(voidptr);
1344 fprintf(file,"==========================================================\n");
1346 #endif /* !defined(NDEBUG) */
1349 * These are local overrides for various environment variables in Emacs.
1350 * Please do not remove this and leave it at the end of the file, where
1351 * Emacs will automagically detect them.
1352 * ---------------------------------------------------------------------
1355 * indent-tabs-mode: t
1359 * vim:noexpandtab:sw=4:ts=4: