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 7464 2007-03-06 00:26:31Z edwin $
38 #include "mm/memory.h"
40 #include "vm/exceptions.h"
42 #include "vm/jit_interface.h"
44 #include "vmcore/descriptor.h"
45 #include "vmcore/options.h"
48 /* constants (private to descriptor.c) ****************************************/
50 /* initial number of entries for the classrefhash of a descriptor_pool */
51 /* (currently the hash is never grown!) */
52 #define CLASSREFHASH_INIT_SIZE 64
54 /* initial number of entries for the descriptorhash of a descriptor_pool */
55 /* (currently the hash is never grown!) */
56 #define DESCRIPTORHASH_INIT_SIZE 128
58 /* data structures (private to descriptor.c) **********************************/
60 typedef struct classref_hash_entry classref_hash_entry;
61 typedef struct descriptor_hash_entry descriptor_hash_entry;
63 /* entry struct for the classrefhash of descriptor_pool */
64 struct classref_hash_entry {
65 classref_hash_entry *hashlink; /* for hash chaining */
66 utf *name; /* name of the class refered to */
67 u2 index; /* index into classref table */
70 /* entry struct for the descriptorhash of descriptor_pool */
71 struct descriptor_hash_entry {
72 descriptor_hash_entry *hashlink;
74 parseddesc parseddesc;
75 s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
79 /****************************************************************************/
80 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
81 /****************************************************************************/
83 /* SKIP_FIELDDESCRIPTOR:
84 * utf_ptr must point to the first character of a field descriptor.
85 * After the macro call utf_ptr points to the first character after
86 * the field descriptor.
88 * CAUTION: This macro does not check for an unexpected end of the
89 * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
91 #define SKIP_FIELDDESCRIPTOR(utf_ptr) \
92 do { while (*(utf_ptr)=='[') (utf_ptr)++; \
93 if (*(utf_ptr)++=='L') \
94 while(*(utf_ptr)++ != ';') /* skip */; } while(0)
96 /* SKIP_FIELDDESCRIPTOR_SAFE:
97 * utf_ptr must point to the first character of a field descriptor.
98 * After the macro call utf_ptr points to the first character after
99 * the field descriptor.
102 * utf_ptr....points to first char of descriptor
103 * end_ptr....points to first char after the end of the string
104 * errorflag..must be initialized (to false) by the caller!
106 * utf_ptr....points to first char after the descriptor
107 * errorflag..set to true if the string ended unexpectedly
109 #define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
110 do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
111 if ((utf_ptr) == (end_ptr)) \
112 (errorflag) = true; \
114 if (*(utf_ptr)++=='L') { \
115 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
117 if ((utf_ptr)[-1] != ';') \
118 (errorflag) = true; }} while(0)
121 /****************************************************************************/
123 /****************************************************************************/
125 /*#define DESCRIPTOR_VERBOSE*/
127 /****************************************************************************/
129 /****************************************************************************/
131 /* descriptor_to_basic_type ****************************************************
133 Return the basic type to use for a value with this descriptor.
136 utf..............descriptor utf string
142 This function assumes that the descriptor has passed
143 descriptor_pool_add checks and that it does not start with '('.
145 *******************************************************************************/
147 u2 descriptor_to_basic_type(utf *descriptor)
149 assert(descriptor->blength >= 1);
151 switch (descriptor->text[0]) {
156 case 'Z': return TYPE_INT;
157 case 'D': return TYPE_DBL;
158 case 'F': return TYPE_FLT;
159 case 'J': return TYPE_LNG;
161 case '[': return TYPE_ADR;
166 return 0; /* keep the compiler happy */
169 /* descriptor_typesize**** ****************************************************
171 Return the size in bytes needed for the given type.
174 td..............typedesc describing the type
179 *******************************************************************************/
181 u2 descriptor_typesize(typedesc *td)
186 case TYPE_INT: return 4;
187 case TYPE_LNG: return 8;
188 case TYPE_FLT: return 4;
189 case TYPE_DBL: return 8;
190 case TYPE_ADR: return sizeof(voidptr);
195 return 0; /* keep the compiler happy */
198 /* name_from_descriptor ********************************************************
200 Return the class name indicated by the given descriptor
201 (Internally used helper function)
204 c................class containing the descriptor
205 utf_ptr..........first character of descriptor
206 end_ptr..........first character after the end of the string
207 mode.............a combination (binary or) of the following flags:
209 (Flags marked with * are the default settings.)
211 How to handle "V" descriptors:
213 * DESCRIPTOR_VOID.....handle it like other primitive types
214 DESCRIPTOR_NOVOID...treat it as an error
216 How to deal with extra characters after the end of the
219 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
220 DESCRIPTOR_CHECKEND.....treat them as an error
223 *next............if non-NULL, *next is set to the first character after
224 the descriptor. (Undefined if an error occurs.)
225 *name............set to the utf name of the class
228 true.............descriptor parsed successfully
229 false............an exception has been thrown
231 *******************************************************************************/
233 #define DESCRIPTOR_VOID 0 /* default */
234 #define DESCRIPTOR_NOVOID 0x0040
235 #define DESCRIPTOR_NOCHECKEND 0 /* default */
236 #define DESCRIPTOR_CHECKEND 0x1000
239 name_from_descriptor(classinfo *c,
240 char *utf_ptr, char *end_ptr,
241 char **next, int mode, utf **name)
243 char *start = utf_ptr;
252 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
254 if (mode & DESCRIPTOR_CHECKEND)
255 error |= (utf_ptr != end_ptr);
258 if (next) *next = utf_ptr;
262 if (mode & DESCRIPTOR_NOVOID)
280 *name = utf_new(start, utf_ptr - start);
285 exceptions_throw_classformaterror(c, "Invalid descriptor");
290 /* descriptor_to_typedesc ******************************************************
292 Parse the given type descriptor and fill a typedesc struct
293 (Internally used helper function)
296 pool.............the descriptor pool
297 utf_ptr..........points to first character of type descriptor
298 end_pos..........points after last character of the whole descriptor
301 *next............set to next character after type descriptor
302 *d...............filled with parsed information
305 true.............parsing succeeded
306 false............an exception has been thrown
308 *******************************************************************************/
311 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
312 char **next, typedesc *td)
316 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
320 /* a reference type */
322 td->decltype = TYPE_ADR;
324 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
326 td->classref = descriptor_pool_lookup_classref(pool, name);
329 /* a primitive type */
332 td->decltype = PRIMITIVETYPE_BYTE;
336 td->decltype = PRIMITIVETYPE_CHAR;
340 td->decltype = PRIMITIVETYPE_SHORT;
344 td->decltype = PRIMITIVETYPE_BOOLEAN;
348 td->decltype = PRIMITIVETYPE_INT;
352 td->decltype = PRIMITIVETYPE_DOUBLE;
356 td->decltype = PRIMITIVETYPE_FLOAT;
360 td->decltype = PRIMITIVETYPE_LONG;
364 td->decltype = PRIMITIVETYPE_VOID;
365 td->type = TYPE_VOID;
379 /* descriptor_pool_new *********************************************************
381 Allocate a new descriptor_pool
384 referer..........class for which to create the pool
387 a pointer to the new descriptor_pool
389 *******************************************************************************/
392 descriptor_pool_new(classinfo *referer)
394 descriptor_pool *pool;
398 pool = DNEW(descriptor_pool);
401 pool->referer = referer;
402 pool->fieldcount = 0;
403 pool->methodcount = 0;
404 pool->paramcount = 0;
405 pool->descriptorsize = 0;
406 pool->descriptors = NULL;
407 pool->descriptors_next = NULL;
408 pool->classrefs = NULL;
409 pool->descriptor_kind = NULL;
410 pool->descriptor_kind_next = NULL;
412 hashsize = CLASSREFHASH_INIT_SIZE;
413 pool->classrefhash.size = hashsize;
414 pool->classrefhash.entries = 0;
415 pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
416 for (slot=0; slot<hashsize; ++slot)
417 pool->classrefhash.ptr[slot] = NULL;
419 hashsize = DESCRIPTORHASH_INIT_SIZE;
420 pool->descriptorhash.size = hashsize;
421 pool->descriptorhash.entries = 0;
422 pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
423 for (slot=0; slot<hashsize; ++slot)
424 pool->descriptorhash.ptr[slot] = NULL;
430 /* descriptor_pool_add_class ***************************************************
432 Add the given class reference to the pool
435 pool.............the descriptor_pool
436 name.............the class reference to add
439 true.............reference has been added
440 false............an exception has been thrown
442 *******************************************************************************/
445 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
448 classref_hash_entry *c;
453 #ifdef DESCRIPTOR_VERBOSE
454 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
455 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
458 /* find a place in the hashtable */
460 key = utf_hashkey(name->text, name->blength);
461 slot = key & (pool->classrefhash.size - 1);
462 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
466 return true; /* already stored */
470 /* check if the name is a valid classname */
472 if (!is_valid_name(name->text,UTF_END(name))) {
473 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
474 return false; /* exception */
477 /* XXX check maximum array dimension */
479 c = DNEW(classref_hash_entry);
481 c->index = pool->classrefhash.entries++;
482 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
483 pool->classrefhash.ptr[slot] = c;
489 /* descriptor_pool_add *********************************************************
491 Check the given descriptor and add it to the pool
494 pool.............the descriptor_pool
495 desc.............the descriptor to add. Maybe a field or method desc.
498 *paramslots......if non-NULL, set to the number of parameters.
499 LONG and DOUBLE are counted twice
502 true.............descriptor has been added
503 false............an exception has been thrown
505 *******************************************************************************/
508 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
511 descriptor_hash_entry *d;
517 #ifdef DESCRIPTOR_VERBOSE
518 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
519 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
525 /* find a place in the hashtable */
527 key = utf_hashkey(desc->text, desc->blength);
528 slot = key & (pool->descriptorhash.size - 1);
529 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
531 /* Save all method descriptors in the hashtable, since the parsed */
532 /* descriptor may vary between differenf methods (static vs. non-static). */
534 utf_ptr = desc->text;
536 if (*utf_ptr != '(') {
538 if (d->desc == desc) {
540 *paramslots = d->paramslots;
541 return true; /* already stored */
547 /* add the descriptor to the pool */
549 d = DNEW(descriptor_hash_entry);
551 d->parseddesc.any = NULL;
552 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
553 pool->descriptorhash.ptr[slot] = d;
555 /* now check the descriptor */
557 end_pos = UTF_END(desc);
559 if (*utf_ptr == '(') {
560 /* a method descriptor */
565 /* check arguments */
567 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
570 /* We cannot count the `this' argument here because
571 * we don't know if the method is static. */
573 if (*utf_ptr == 'J' || *utf_ptr == 'D')
578 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
579 DESCRIPTOR_NOVOID, &name))
583 if (!descriptor_pool_add_class(pool, name))
587 if (utf_ptr == end_pos) {
588 exceptions_throw_classformaterror(pool->referer,
589 "Missing ')' in method descriptor");
593 utf_ptr++; /* skip ')' */
595 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
596 DESCRIPTOR_CHECKEND, &name))
600 if (!descriptor_pool_add_class(pool,name))
603 if (argcount > 255) {
604 exceptions_throw_classformaterror(pool->referer,
605 "Too many arguments in signature");
610 /* a field descriptor */
614 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
615 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
620 if (!descriptor_pool_add_class(pool,name))
624 d->paramslots = argcount;
627 *paramslots = argcount;
633 /* descriptor_pool_create_classrefs ********************************************
635 Create a table containing all the classrefs which were added to the pool
638 pool.............the descriptor_pool
641 *count...........if count is non-NULL, this is set to the number
642 of classrefs in the table
645 a pointer to the constant_classref table
647 *******************************************************************************/
650 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
654 classref_hash_entry *c;
655 constant_classref *ref;
659 nclasses = pool->classrefhash.entries;
660 pool->classrefs = MNEW(constant_classref,nclasses);
662 /* fill the constant_classref structs */
664 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
665 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
667 ref = pool->classrefs + c->index;
668 CLASSREF_INIT(*ref, pool->referer, c->name);
676 return pool->classrefs;
680 /* descriptor_pool_lookup_classref *********************************************
682 Return the constant_classref for the given class name
685 pool.............the descriptor_pool
686 classname........name of the class to look up
689 a pointer to the constant_classref, or
690 NULL if an exception has been thrown
692 *******************************************************************************/
695 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
698 classref_hash_entry *c;
701 assert(pool->classrefs);
704 key = utf_hashkey(classname->text, classname->blength);
705 slot = key & (pool->classrefhash.size - 1);
706 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
709 if (c->name == classname)
710 return pool->classrefs + c->index;
714 exceptions_throw_internalerror("Class reference not found in descriptor pool");
719 /* descriptor_pool_alloc_parsed_descriptors ************************************
721 Allocate space for the parsed descriptors
724 pool.............the descriptor_pool
727 This function must be called after all descriptors have been added
728 with descriptor_pool_add.
730 *******************************************************************************/
733 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
739 /* TWISTI: paramcount + 1: we don't know if the method is static or */
740 /* not, i have no better solution yet. */
743 pool->fieldcount * sizeof(typedesc) +
744 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
745 pool->paramcount * sizeof(typedesc) +
746 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
748 pool->descriptorsize = size;
750 pool->descriptors = MNEW(u1, size);
751 pool->descriptors_next = pool->descriptors;
754 size = pool->fieldcount + pool->methodcount;
756 pool->descriptor_kind = DMNEW(u1, size);
757 pool->descriptor_kind_next = pool->descriptor_kind;
762 /* descriptor_pool_parse_field_descriptor **************************************
764 Parse the given field descriptor
767 pool.............the descriptor_pool
768 desc.............the field descriptor
771 a pointer to the parsed field descriptor, or
772 NULL if an exception has been thrown
775 descriptor_pool_alloc_parsed_descriptors must be called (once)
776 before this function is used.
778 *******************************************************************************/
781 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
784 descriptor_hash_entry *d;
788 assert(pool->descriptors);
789 assert(pool->descriptors_next);
791 /* lookup the descriptor in the hashtable */
793 key = utf_hashkey(desc->text, desc->blength);
794 slot = key & (pool->descriptorhash.size - 1);
795 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
798 if (d->desc == desc) {
800 if (d->parseddesc.fd)
801 return d->parseddesc.fd;
809 if (desc->text[0] == '(') {
810 exceptions_throw_classformaterror(pool->referer,
811 "Method descriptor used in field reference");
815 td = (typedesc *) pool->descriptors_next;
816 pool->descriptors_next += sizeof(typedesc);
818 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
821 *(pool->descriptor_kind_next++) = 'f';
823 d->parseddesc.fd = td;
829 /* descriptor_pool_parse_method_descriptor *************************************
831 Parse the given method descriptor
834 pool.............the descriptor_pool
835 desc.............the method descriptor
836 mflags...........the method flags
837 thisclass........classref to the class containing the method.
838 This is ignored if mflags contains ACC_STATIC.
839 The classref is stored for inserting the 'this' argument.
842 a pointer to the parsed method descriptor, or
843 NULL if an exception has been thrown
846 descriptor_pool_alloc_parsed_descriptors must be called
847 (once) before this function is used.
849 *******************************************************************************/
852 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
853 s4 mflags,constant_classref *thisclass)
856 descriptor_hash_entry *d;
864 #ifdef DESCRIPTOR_VERBOSE
865 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
866 (void*)pool,(int)mflags,(void*)thisclass);
867 utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
871 assert(pool->descriptors);
872 assert(pool->descriptors_next);
874 /* check that it is a method descriptor */
876 if (desc->text[0] != '(') {
877 exceptions_throw_classformaterror(pool->referer,
878 "Field descriptor used in method reference");
882 /* lookup the descriptor in the hashtable */
884 key = utf_hashkey(desc->text, desc->blength);
885 slot = key & (pool->descriptorhash.size - 1);
886 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
888 /* find an un-parsed descriptor */
892 if (!d->parseddesc.md)
899 md = (methoddesc *) pool->descriptors_next;
900 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
902 utf_ptr = desc->text + 1; /* skip '(' */
903 end_pos = UTF_END(desc);
907 /* count the `this' pointer */
909 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
911 td->decltype = TYPE_ADR;
913 td->classref = thisclass;
916 pool->descriptors_next += sizeof(typedesc);
921 while (*utf_ptr != ')') {
922 /* parse a parameter type */
924 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
927 if (IS_2_WORD_TYPE(td->type))
931 pool->descriptors_next += sizeof(typedesc);
935 utf_ptr++; /* skip ')' */
937 /* Skip possible `this' pointer in paramtypes array to allow a possible */
938 /* memory move later in parse. */
939 /* We store the thisclass reference, so we can later correctly fill in */
940 /* the parameter slot of the 'this' argument. */
942 if (mflags == ACC_UNDEF) {
943 td->classref = thisclass;
945 pool->descriptors_next += sizeof(typedesc);
948 /* parse return type */
950 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
954 md->paramcount = paramcount;
955 md->paramslots = paramslots;
957 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
958 /* Otherwise we do this in stack analysis. */
960 if (mflags != ACC_UNDEF) {
961 if (md->paramcount > 0) {
962 /* allocate memory for params */
964 md->params = MNEW(paramdesc, md->paramcount);
967 md->params = METHODDESC_NOPARAMS;
970 /* fill the paramdesc */
971 /* md_param_alloc has to be called if md->paramcount == 0,
972 too, so it can make the reservation for the Linkage Area,
973 Return Register... */
975 #if defined(ENABLE_JIT)
976 # if defined(ENABLE_INTRP)
983 /* params will be allocated later by
984 descriptor_params_from_paramtypes if necessary */
989 *(pool->descriptor_kind_next++) = 'm';
991 d->parseddesc.md = md;
996 /* descriptor_params_from_paramtypes *******************************************
998 Create the paramdescs for a method descriptor. This function is called
999 when we know whether the method is static or not. This function may only
1000 be called once for each methoddesc, and only if md->params == NULL.
1003 md...............the parsed method descriptor
1004 md->params MUST be NULL.
1005 mflags...........the ACC_* access flags of the method. Only the
1006 ACC_STATIC bit is checked.
1007 The value ACC_UNDEF is NOT allowed.
1010 true.............the paramdescs were created successfully
1011 false............an exception has been thrown
1016 *******************************************************************************/
1018 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1023 assert(md->params == NULL);
1024 assert(mflags != ACC_UNDEF);
1026 td = md->paramtypes;
1028 /* check for `this' pointer */
1030 if (!(mflags & ACC_STATIC)) {
1031 constant_classref *thisclass;
1033 /* fetch class reference from reserved param slot */
1034 thisclass = td[md->paramcount].classref;
1037 if (md->paramcount > 0) {
1038 /* shift param types by 1 argument */
1039 MMOVE(td + 1, td, typedesc, md->paramcount);
1042 /* fill in first argument `this' */
1044 td->type = TYPE_ADR;
1045 td->decltype = TYPE_ADR;
1047 td->classref = thisclass;
1053 /* if the method has params, process them */
1055 if (md->paramcount > 0) {
1056 /* allocate memory for params */
1058 md->params = MNEW(paramdesc, md->paramcount);
1061 md->params = METHODDESC_NOPARAMS;
1064 /* fill the paramdesc */
1065 /* md_param_alloc has to be called if md->paramcount == 0, too, so
1066 it can make the reservation for the Linkage Area, Return
1069 #if defined(ENABLE_JIT)
1070 # if defined(ENABLE_INTRP)
1080 /* descriptor_pool_get_parsed_descriptors **************************************
1082 Return a pointer to the block of parsed descriptors
1085 pool.............the descriptor_pool
1088 *size............if size is non-NULL, this is set to the size of the
1089 parsed descriptor block (in u1)
1092 a pointer to the block of parsed descriptors
1095 descriptor_pool_alloc_parsed_descriptors must be called (once)
1096 before this function is used.
1098 *******************************************************************************/
1101 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1104 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1107 *size = pool->descriptorsize;
1109 return pool->descriptors;
1113 /* descriptor_pool_get_sizes ***************************************************
1115 Get the sizes of the class reference table and the parsed descriptors
1118 pool.............the descriptor_pool
1121 *classrefsize....set to size of the class reference table
1122 *descsize........set to size of the parsed descriptors
1125 This function may only be called after both
1126 descriptor_pool_create_classrefs, and
1127 descriptor_pool_alloc_parsed_descriptors
1130 *******************************************************************************/
1133 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1136 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1137 assert(pool->classrefs);
1138 assert(classrefsize);
1141 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1142 *descsize = pool->descriptorsize;
1146 /****************************************************************************/
1148 /****************************************************************************/
1151 /* descriptor_debug_print_typedesc *********************************************
1153 Print the given typedesc to the given stream
1156 file.............stream to print to
1157 d................the parsed descriptor
1159 *******************************************************************************/
1162 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1167 fprintf(file,"(typedesc *)NULL");
1171 if (d->type == TYPE_ADR) {
1173 utf_fprint_printable_ascii(file,d->classref->name);
1175 fprintf(file,"<class=NULL>");
1178 switch (d->decltype) {
1179 case PRIMITIVETYPE_INT : ch='I'; break;
1180 case PRIMITIVETYPE_CHAR : ch='C'; break;
1181 case PRIMITIVETYPE_BYTE : ch='B'; break;
1182 case PRIMITIVETYPE_SHORT : ch='S'; break;
1183 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1184 case PRIMITIVETYPE_LONG : ch='J'; break;
1185 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1186 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1187 case PRIMITIVETYPE_VOID : ch='V'; break;
1193 fprintf(file,"[%d]",d->arraydim);
1196 /* descriptor_debug_print_paramdesc ********************************************
1198 Print the given paramdesc to the given stream
1201 file.............stream to print to
1202 d................the parameter descriptor
1204 *******************************************************************************/
1207 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1210 fprintf(file,"(paramdesc *)NULL");
1215 fprintf(file,"<m%d>",d->regoff);
1218 fprintf(file,"<r%d>",d->regoff);
1222 /* descriptor_debug_print_methoddesc *******************************************
1224 Print the given methoddesc to the given stream
1227 file.............stream to print to
1228 d................the parsed descriptor
1230 *******************************************************************************/
1233 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1238 fprintf(file,"(methoddesc *)NULL");
1243 for (i=0; i<d->paramcount; ++i) {
1246 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1248 descriptor_debug_print_paramdesc(file,d->params + i);
1251 if (d->params == METHODDESC_NOPARAMS)
1252 fputs("<NOPARAMS>",file);
1254 descriptor_debug_print_typedesc(file,&(d->returntype));
1257 /* descriptor_pool_debug_dump **************************************************
1259 Print the state of the descriptor_pool to the given stream
1262 pool.............the descriptor_pool
1263 file.............stream to print to
1265 *******************************************************************************/
1268 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1275 fprintf(file,"======[descriptor_pool for ");
1276 utf_fprint_printable_ascii(file,pool->referer->name);
1277 fprintf(file,"]======\n");
1279 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1280 fprintf(file,"methodcount: %d\n",pool->methodcount);
1281 fprintf(file,"paramcount: %d\n",pool->paramcount);
1282 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1283 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1284 fprintf(file,"classrefsize: %d bytes\n",
1285 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1287 fprintf(file,"class references:\n");
1288 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1289 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1291 fprintf(file," %4d: ",c->index);
1292 utf_fprint_printable_ascii(file,c->name);
1298 fprintf(file,"hashed descriptors:\n");
1299 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1300 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1302 fprintf(file," %p: ",c->parseddesc.any);
1303 utf_fprint_printable_ascii(file,c->desc);
1309 fprintf(file,"descriptors:\n");
1310 if (pool->descriptors) {
1311 pos = pool->descriptors;
1312 size = pool->descriptors_next - pool->descriptors;
1313 fprintf(file," size: %d bytes\n",size);
1315 if (pool->descriptor_kind) {
1316 kind = pool->descriptor_kind;
1318 while (pos < (pool->descriptors + size)) {
1319 fprintf(file," %p: ",pos);
1322 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1323 pos += sizeof(typedesc);
1326 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1327 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1328 pos += sizeof(methoddesc) - sizeof(typedesc);
1331 fprintf(file,"INVALID KIND");
1337 while (size >= sizeof(voidptr)) {
1338 fprintf(file," %p\n",*((voidptr*)pos));
1339 pos += sizeof(voidptr);
1340 size -= sizeof(voidptr);
1345 fprintf(file,"==========================================================\n");
1347 #endif /* !defined(NDEBUG) */
1350 * These are local overrides for various environment variables in Emacs.
1351 * Please do not remove this and leave it at the end of the file, where
1352 * Emacs will automagically detect them.
1353 * ---------------------------------------------------------------------
1356 * indent-tabs-mode: t
1360 * vim:noexpandtab:sw=4:ts=4: