1 /* src/vm/descriptor.c - checking and parsing of field / method descriptors
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Edwin Steiner
29 Changes: Christian Thalinger
32 $Id: descriptor.c 3386 2005-10-07 14:02:52Z edwin $
42 #include "mm/memory.h"
43 #include "vm/descriptor.h"
44 #include "vm/exceptions.h"
45 #include "vm/resolve.h"
46 #include "vm/stringlocal.h"
49 /* constants (private to descriptor.c) ****************************************/
51 /* initial number of entries for the classrefhash of a descriptor_pool */
52 /* (currently the hash is never grown!) */
53 #define CLASSREFHASH_INIT_SIZE 64
55 /* initial number of entries for the descriptorhash of a descriptor_pool */
56 /* (currently the hash is never grown!) */
57 #define DESCRIPTORHASH_INIT_SIZE 128
59 /* data structures (private to descriptor.c) **********************************/
61 typedef struct classref_hash_entry classref_hash_entry;
62 typedef struct descriptor_hash_entry descriptor_hash_entry;
64 /* entry struct for the classrefhash of descriptor_pool */
65 struct classref_hash_entry {
66 classref_hash_entry *hashlink; /* for hash chaining */
67 utf *name; /* name of the class refered to */
68 u2 index; /* index into classref table */
71 /* entry struct for the descriptorhash of descriptor_pool */
72 struct descriptor_hash_entry {
73 descriptor_hash_entry *hashlink;
75 parseddesc parseddesc;
76 s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
80 /****************************************************************************/
81 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
82 /****************************************************************************/
84 /* SKIP_FIELDDESCRIPTOR:
85 * utf_ptr must point to the first character of a field descriptor.
86 * After the macro call utf_ptr points to the first character after
87 * the field descriptor.
89 * CAUTION: This macro does not check for an unexpected end of the
90 * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
92 #define SKIP_FIELDDESCRIPTOR(utf_ptr) \
93 do { while (*(utf_ptr)=='[') (utf_ptr)++; \
94 if (*(utf_ptr)++=='L') \
95 while(*(utf_ptr)++ != ';') /* skip */; } while(0)
97 /* SKIP_FIELDDESCRIPTOR_SAFE:
98 * utf_ptr must point to the first character of a field descriptor.
99 * After the macro call utf_ptr points to the first character after
100 * the field descriptor.
103 * utf_ptr....points to first char of descriptor
104 * end_ptr....points to first char after the end of the string
105 * errorflag..must be initialized (to false) by the caller!
107 * utf_ptr....points to first char after the descriptor
108 * errorflag..set to true if the string ended unexpectedly
110 #define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
111 do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
112 if ((utf_ptr) == (end_ptr)) \
113 (errorflag) = true; \
115 if (*(utf_ptr)++=='L') { \
116 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
118 if ((utf_ptr)[-1] != ';') \
119 (errorflag) = true; }} while(0)
122 /****************************************************************************/
124 /****************************************************************************/
126 /*#define DESCRIPTOR_VERBOSE*/
129 #define DESCRIPTOR_DEBUG
132 #ifdef DESCRIPTOR_DEBUG
133 #define DESCRIPTOR_ASSERT(cond) assert(cond)
135 #define DESCRIPTOR_ASSERT(cond)
138 /* name_from_descriptor ********************************************************
140 Return the class name indicated by the given descriptor
141 (Internally used helper function)
144 c................class containing the descriptor
145 utf_ptr..........first character of descriptor
146 end_ptr..........first character after the end of the string
147 mode.............a combination (binary or) of the following flags:
149 (Flags marked with * are the default settings.)
151 How to handle "V" descriptors:
153 * DESCRIPTOR_VOID.....handle it like other primitive types
154 DESCRIPTOR_NOVOID...treat it as an error
156 How to deal with extra characters after the end of the
159 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
160 DESCRIPTOR_CHECKEND.....treat them as an error
163 *next............if non-NULL, *next is set to the first character after
164 the descriptor. (Undefined if an error occurs.)
165 *name............set to the utf name of the class
168 true.............descriptor parsed successfully
169 false............an exception has been thrown
171 *******************************************************************************/
173 #define DESCRIPTOR_VOID 0 /* default */
174 #define DESCRIPTOR_NOVOID 0x0040
175 #define DESCRIPTOR_NOCHECKEND 0 /* default */
176 #define DESCRIPTOR_CHECKEND 0x1000
179 name_from_descriptor(classinfo *c,
180 char *utf_ptr, char *end_ptr,
181 char **next, int mode, utf **name)
183 char *start = utf_ptr;
186 DESCRIPTOR_ASSERT(c);
187 DESCRIPTOR_ASSERT(utf_ptr);
188 DESCRIPTOR_ASSERT(end_ptr);
189 DESCRIPTOR_ASSERT(name);
192 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
194 if (mode & DESCRIPTOR_CHECKEND)
195 error |= (utf_ptr != end_ptr);
198 if (next) *next = utf_ptr;
202 if (mode & DESCRIPTOR_NOVOID)
220 *name = utf_new(start, utf_ptr - start);
225 *exceptionptr = new_classformaterror(c,"invalid descriptor");
230 /* descriptor_to_typedesc ******************************************************
232 Parse the given type descriptor and fill a typedesc struct
233 (Internally used helper function)
236 pool.............the descriptor pool
237 utf_ptr..........points to first character of type descriptor
238 end_pos..........points after last character of the whole descriptor
241 *next............set to next character after type descriptor
242 *d...............filled with parsed information
245 true.............parsing succeeded
246 false............an exception has been thrown
248 *******************************************************************************/
251 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
252 char **next, typedesc *td)
256 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
260 /* a reference type */
261 td->type = TYPE_ADDRESS;
262 td->decltype = TYPE_ADDRESS;
264 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
266 td->classref = descriptor_pool_lookup_classref(pool, name);
269 /* a primitive type */
272 td->decltype = PRIMITIVETYPE_BYTE;
276 td->decltype = PRIMITIVETYPE_CHAR;
280 td->decltype = PRIMITIVETYPE_SHORT;
284 td->decltype = PRIMITIVETYPE_BOOLEAN;
288 td->decltype = PRIMITIVETYPE_INT;
292 td->decltype = PRIMITIVETYPE_DOUBLE;
293 td->type = TYPE_DOUBLE;
296 td->decltype = PRIMITIVETYPE_FLOAT;
297 td->type = TYPE_FLOAT;
300 td->decltype = PRIMITIVETYPE_LONG;
301 td->type = TYPE_LONG;
304 td->decltype = PRIMITIVETYPE_VOID;
305 td->type = TYPE_VOID;
308 DESCRIPTOR_ASSERT(false);
319 /* descriptor_pool_new *********************************************************
321 Allocate a new descriptor_pool
324 referer..........class for which to create the pool
327 a pointer to the new descriptor_pool
329 *******************************************************************************/
332 descriptor_pool_new(classinfo *referer)
334 descriptor_pool *pool;
338 pool = DNEW(descriptor_pool);
339 DESCRIPTOR_ASSERT(pool);
341 pool->referer = referer;
342 pool->fieldcount = 0;
343 pool->methodcount = 0;
344 pool->paramcount = 0;
345 pool->descriptorsize = 0;
346 pool->descriptors = NULL;
347 pool->descriptors_next = NULL;
348 pool->classrefs = NULL;
349 pool->descriptor_kind = NULL;
350 pool->descriptor_kind_next = NULL;
352 hashsize = CLASSREFHASH_INIT_SIZE;
353 pool->classrefhash.size = hashsize;
354 pool->classrefhash.entries = 0;
355 pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
356 for (slot=0; slot<hashsize; ++slot)
357 pool->classrefhash.ptr[slot] = NULL;
359 hashsize = DESCRIPTORHASH_INIT_SIZE;
360 pool->descriptorhash.size = hashsize;
361 pool->descriptorhash.entries = 0;
362 pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
363 for (slot=0; slot<hashsize; ++slot)
364 pool->descriptorhash.ptr[slot] = NULL;
370 /* descriptor_pool_add_class ***************************************************
372 Add the given class reference to the pool
375 pool.............the descriptor_pool
376 name.............the class reference to add
379 true.............reference has been added
380 false............an exception has been thrown
382 *******************************************************************************/
385 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
388 classref_hash_entry *c;
390 DESCRIPTOR_ASSERT(pool);
391 DESCRIPTOR_ASSERT(name);
393 #ifdef DESCRIPTOR_VERBOSE
394 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
395 utf_fprint(stderr,name);fprintf(stderr,")\n");
398 /* find a place in the hashtable */
400 key = utf_hashkey(name->text, name->blength);
401 slot = key & (pool->classrefhash.size - 1);
402 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
406 return true; /* already stored */
410 /* check if the name is a valid classname */
412 if (!is_valid_name(name->text,UTF_END(name))) {
413 *exceptionptr = new_classformaterror(pool->referer,
414 "Invalid class name");
415 return false; /* exception */
418 /* XXX check maximum array dimension */
420 c = DNEW(classref_hash_entry);
422 c->index = pool->classrefhash.entries++;
423 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
424 pool->classrefhash.ptr[slot] = c;
430 /* descriptor_pool_add *********************************************************
432 Check the given descriptor and add it to the pool
435 pool.............the descriptor_pool
436 desc.............the descriptor to add. Maybe a field or method desc.
439 *paramslots......if non-NULL, set to the number of parameters.
440 LONG and DOUBLE are counted twice
443 true.............descriptor has been added
444 false............an exception has been thrown
446 *******************************************************************************/
449 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
452 descriptor_hash_entry *d;
458 #ifdef DESCRIPTOR_VERBOSE
459 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
460 utf_fprint(stderr,desc);fprintf(stderr,")\n");
463 DESCRIPTOR_ASSERT(pool);
464 DESCRIPTOR_ASSERT(desc);
466 /* find a place in the hashtable */
468 key = utf_hashkey(desc->text, desc->blength);
469 slot = key & (pool->descriptorhash.size - 1);
470 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
472 /* Save all method descriptors in the hashtable, since the parsed */
473 /* descriptor may vary between differenf methods (static vs. non-static). */
475 utf_ptr = desc->text;
477 if (*utf_ptr != '(') {
479 if (d->desc == desc) {
481 *paramslots = d->paramslots;
482 return true; /* already stored */
488 /* add the descriptor to the pool */
490 d = DNEW(descriptor_hash_entry);
492 d->parseddesc.any = NULL;
493 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
494 pool->descriptorhash.ptr[slot] = d;
496 /* now check the descriptor */
498 end_pos = UTF_END(desc);
500 if (*utf_ptr == '(') {
501 /* a method descriptor */
506 /* check arguments */
508 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
511 /* We cannot count the `this' argument here because
512 * we don't know if the method is static. */
514 if (*utf_ptr == 'J' || *utf_ptr == 'D')
519 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
520 DESCRIPTOR_NOVOID, &name))
524 if (!descriptor_pool_add_class(pool, name))
528 if (utf_ptr == end_pos) {
529 *exceptionptr = new_classformaterror(pool->referer,"Missing ')' in method descriptor");
533 utf_ptr++; /* skip ')' */
535 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
536 DESCRIPTOR_CHECKEND, &name))
540 if (!descriptor_pool_add_class(pool,name))
543 if (argcount > 255) {
545 new_classformaterror(pool->referer,"Too many arguments in signature");
550 /* a field descriptor */
554 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
555 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
560 if (!descriptor_pool_add_class(pool,name))
564 d->paramslots = argcount;
567 *paramslots = argcount;
573 /* descriptor_pool_create_classrefs ********************************************
575 Create a table containing all the classrefs which were added to the pool
578 pool.............the descriptor_pool
581 *count...........if count is non-NULL, this is set to the number
582 of classrefs in the table
585 a pointer to the constant_classref table
587 *******************************************************************************/
590 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
594 classref_hash_entry *c;
595 constant_classref *ref;
597 DESCRIPTOR_ASSERT(pool);
599 nclasses = pool->classrefhash.entries;
600 pool->classrefs = MNEW(constant_classref,nclasses);
602 /* fill the constant_classref structs */
604 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
605 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
607 ref = pool->classrefs + c->index;
608 CLASSREF_INIT(*ref, pool->referer, c->name);
616 return pool->classrefs;
620 /* descriptor_pool_lookup_classref *********************************************
622 Return the constant_classref for the given class name
625 pool.............the descriptor_pool
626 classname........name of the class to look up
629 a pointer to the constant_classref, or
630 NULL if an exception has been thrown
632 *******************************************************************************/
635 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
638 classref_hash_entry *c;
640 DESCRIPTOR_ASSERT(pool);
641 DESCRIPTOR_ASSERT(pool->classrefs);
642 DESCRIPTOR_ASSERT(classname);
644 key = utf_hashkey(classname->text, classname->blength);
645 slot = key & (pool->classrefhash.size - 1);
646 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
649 if (c->name == classname)
650 return pool->classrefs + c->index;
654 *exceptionptr = new_internalerror("Class reference not found in descriptor pool");
659 /* descriptor_pool_alloc_parsed_descriptors ************************************
661 Allocate space for the parsed descriptors
664 pool.............the descriptor_pool
667 This function must be called after all descriptors have been added
668 with descriptor_pool_add.
670 *******************************************************************************/
673 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
677 DESCRIPTOR_ASSERT(pool);
679 /* TWISTI: paramcount + 1: we don't know if the method is static or */
680 /* not, i have no better solution yet. */
683 pool->fieldcount * sizeof(typedesc) +
684 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
685 pool->paramcount * sizeof(typedesc) +
686 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
688 pool->descriptorsize = size;
690 pool->descriptors = MNEW(u1, size);
691 pool->descriptors_next = pool->descriptors;
694 size = pool->fieldcount + pool->methodcount;
696 pool->descriptor_kind = DMNEW(u1, size);
697 pool->descriptor_kind_next = pool->descriptor_kind;
702 /* descriptor_pool_parse_field_descriptor **************************************
704 Parse the given field descriptor
707 pool.............the descriptor_pool
708 desc.............the field descriptor
711 a pointer to the parsed field descriptor, or
712 NULL if an exception has been thrown
715 descriptor_pool_alloc_parsed_descriptors must be called (once)
716 before this function is used.
718 *******************************************************************************/
721 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
724 descriptor_hash_entry *d;
727 DESCRIPTOR_ASSERT(pool);
728 DESCRIPTOR_ASSERT(pool->descriptors);
729 DESCRIPTOR_ASSERT(pool->descriptors_next);
731 /* lookup the descriptor in the hashtable */
733 key = utf_hashkey(desc->text, desc->blength);
734 slot = key & (pool->descriptorhash.size - 1);
735 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
738 if (d->desc == desc) {
740 if (d->parseddesc.fd)
741 return d->parseddesc.fd;
747 DESCRIPTOR_ASSERT(d);
749 if (desc->text[0] == '(') {
750 *exceptionptr = new_classformaterror(pool->referer,
751 "Method descriptor used in field reference");
755 td = (typedesc *) pool->descriptors_next;
756 pool->descriptors_next += sizeof(typedesc);
758 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
761 *(pool->descriptor_kind_next++) = 'f';
763 d->parseddesc.fd = td;
769 /* descriptor_pool_parse_method_descriptor *************************************
771 Parse the given method descriptor
774 pool.............the descriptor_pool
775 desc.............the method descriptor
776 mflags...........the method flags
777 thisclass........classref to the class containing the method.
778 This is ignored if mflags contains ACC_STATIC.
779 The classref is stored for inserting the 'this' argument.
782 a pointer to the parsed method descriptor, or
783 NULL if an exception has been thrown
786 descriptor_pool_alloc_parsed_descriptors must be called
787 (once) before this function is used.
789 *******************************************************************************/
792 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
793 s4 mflags,constant_classref *thisclass)
796 descriptor_hash_entry *d;
804 #ifdef DESCRIPTOR_VERBOSE
805 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
806 (void*)pool,(int)mflags,(void*)thisclass);
807 utf_fprint(stderr,desc); fprintf(stderr,")\n");
810 DESCRIPTOR_ASSERT(pool);
811 DESCRIPTOR_ASSERT(pool->descriptors);
812 DESCRIPTOR_ASSERT(pool->descriptors_next);
814 /* check that it is a method descriptor */
816 if (desc->text[0] != '(') {
817 *exceptionptr = new_classformaterror(pool->referer,
818 "Field descriptor used in method reference");
822 /* lookup the descriptor in the hashtable */
824 key = utf_hashkey(desc->text, desc->blength);
825 slot = key & (pool->descriptorhash.size - 1);
826 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
828 /* find an un-parsed descriptor */
832 if (!d->parseddesc.md)
837 DESCRIPTOR_ASSERT(d);
839 md = (methoddesc *) pool->descriptors_next;
840 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
842 utf_ptr = desc->text + 1; /* skip '(' */
843 end_pos = UTF_END(desc);
847 /* count the `this' pointer */
849 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
851 td->decltype = TYPE_ADR;
853 td->classref = thisclass;
856 pool->descriptors_next += sizeof(typedesc);
861 while (*utf_ptr != ')') {
862 /* parse a parameter type */
864 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
867 if (td->type == TYPE_LONG || td->type == TYPE_DOUBLE)
871 pool->descriptors_next += sizeof(typedesc);
875 utf_ptr++; /* skip ')' */
877 /* Skip possible `this' pointer in paramtypes array to allow a possible */
878 /* memory move later in parse. */
879 /* We store the thisclass reference, so we can later correctly fill in */
880 /* the parameter slot of the 'this' argument. */
882 if (mflags == ACC_UNDEF) {
883 td->classref = thisclass;
885 pool->descriptors_next += sizeof(typedesc);
888 /* parse return type */
890 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
894 md->paramcount = paramcount;
895 md->paramslots = paramslots;
897 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
898 /* Otherwise we do this in stack analysis. */
900 if (mflags != ACC_UNDEF) {
901 if (md->paramcount > 0) {
902 /* allocate memory for params */
904 md->params = MNEW(paramdesc, md->paramcount);
907 md->params = METHODDESC_NOPARAMS;
910 /* fill the paramdesc */
911 /* md_param_alloc has to be called if md->paramcount == 0, too, so it */
912 /* can make the reservation for the Linkage Area, Return Register... */
916 /* params will be allocated later by descriptor_params_from_paramtypes */
921 *(pool->descriptor_kind_next++) = 'm';
923 d->parseddesc.md = md;
928 /* descriptor_params_from_paramtypes *******************************************
930 Create the paramdescs for a method descriptor. This function is called
931 when we know whether the method is static or not. This function may only
932 be called once for each methoddesc, and only if md->params == NULL.
935 md...............the parsed method descriptor
936 md->params MUST be NULL.
937 mflags...........the ACC_* access flags of the method. Only the
938 ACC_STATIC bit is checked.
939 The value ACC_UNDEF is NOT allowed.
942 true.............the paramdescs were created successfully
943 false............an exception has been thrown
948 *******************************************************************************/
950 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
954 DESCRIPTOR_ASSERT(md);
955 DESCRIPTOR_ASSERT(md->params == NULL);
956 DESCRIPTOR_ASSERT(mflags != ACC_UNDEF);
960 /* check for `this' pointer */
962 if (!(mflags & ACC_STATIC)) {
963 constant_classref *thisclass;
965 /* fetch class reference from reserved param slot */
966 thisclass = td[md->paramcount].classref;
967 DESCRIPTOR_ASSERT(thisclass);
969 if (md->paramcount > 0) {
970 /* shift param types by 1 argument */
971 MMOVE(td + 1, td, typedesc, md->paramcount);
974 /* fill in first argument `this' */
977 td->decltype = TYPE_ADR;
979 td->classref = thisclass;
985 /* if the method has params, process them */
987 if (md->paramcount > 0) {
988 /* allocate memory for params */
990 md->params = MNEW(paramdesc, md->paramcount);
993 md->params = METHODDESC_NOPARAMS;
996 /* fill the paramdesc */
997 /* md_param_alloc has to be called if md->paramcount == 0, too, so */
998 /* it can make the reservation for the Linkage Area, Return Register.. */
1006 /* descriptor_pool_get_parsed_descriptors **************************************
1008 Return a pointer to the block of parsed descriptors
1011 pool.............the descriptor_pool
1014 *size............if size is non-NULL, this is set to the size of the
1015 parsed descriptor block (in u1)
1018 a pointer to the block of parsed descriptors
1021 descriptor_pool_alloc_parsed_descriptors must be called (once)
1022 before this function is used.
1024 *******************************************************************************/
1027 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1029 DESCRIPTOR_ASSERT(pool);
1030 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1033 *size = pool->descriptorsize;
1035 return pool->descriptors;
1039 /* descriptor_pool_get_sizes ***************************************************
1041 Get the sizes of the class reference table and the parsed descriptors
1044 pool.............the descriptor_pool
1047 *classrefsize....set to size of the class reference table
1048 *descsize........set to size of the parsed descriptors
1051 This function may only be called after both
1052 descriptor_pool_create_classrefs, and
1053 descriptor_pool_alloc_parsed_descriptors
1056 *******************************************************************************/
1059 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1061 DESCRIPTOR_ASSERT(pool);
1062 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1063 DESCRIPTOR_ASSERT(pool->classrefs);
1064 DESCRIPTOR_ASSERT(classrefsize);
1065 DESCRIPTOR_ASSERT(descsize);
1067 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1068 *descsize = pool->descriptorsize;
1072 /* descriptor_debug_print_typedesc *********************************************
1074 Print the given typedesc to the given stream
1077 file.............stream to print to
1078 d................the parsed descriptor
1080 *******************************************************************************/
1083 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1088 fprintf(file,"(typedesc *)NULL");
1092 if (d->type == TYPE_ADDRESS) {
1094 utf_fprint(file,d->classref->name);
1096 fprintf(file,"<class=NULL>");
1099 switch (d->decltype) {
1100 case PRIMITIVETYPE_INT : ch='I'; break;
1101 case PRIMITIVETYPE_CHAR : ch='C'; break;
1102 case PRIMITIVETYPE_BYTE : ch='B'; break;
1103 case PRIMITIVETYPE_SHORT : ch='S'; break;
1104 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1105 case PRIMITIVETYPE_LONG : ch='J'; break;
1106 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1107 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1108 case PRIMITIVETYPE_VOID : ch='V'; break;
1114 fprintf(file,"[%d]",d->arraydim);
1117 /* descriptor_debug_print_paramdesc ********************************************
1119 Print the given paramdesc to the given stream
1122 file.............stream to print to
1123 d................the parameter descriptor
1125 *******************************************************************************/
1128 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1131 fprintf(file,"(paramdesc *)NULL");
1136 fprintf(file,"<m%d>",d->regoff);
1139 fprintf(file,"<r%d>",d->regoff);
1143 /* descriptor_debug_print_methoddesc *******************************************
1145 Print the given methoddesc to the given stream
1148 file.............stream to print to
1149 d................the parsed descriptor
1151 *******************************************************************************/
1154 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1159 fprintf(file,"(methoddesc *)NULL");
1164 for (i=0; i<d->paramcount; ++i) {
1167 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1169 descriptor_debug_print_paramdesc(file,d->params + i);
1172 if (d->params == METHODDESC_NOPARAMS)
1173 fputs("<NOPARAMS>",file);
1175 descriptor_debug_print_typedesc(file,&(d->returntype));
1178 /* descriptor_pool_debug_dump **************************************************
1180 Print the state of the descriptor_pool to the given stream
1183 pool.............the descriptor_pool
1184 file.............stream to print to
1186 *******************************************************************************/
1189 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1196 fprintf(file,"======[descriptor_pool for ");
1197 utf_fprint(file,pool->referer->name);
1198 fprintf(file,"]======\n");
1200 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1201 fprintf(file,"methodcount: %d\n",pool->methodcount);
1202 fprintf(file,"paramcount: %d\n",pool->paramcount);
1203 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1204 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1205 fprintf(file,"classrefsize: %d bytes\n",
1206 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1208 fprintf(file,"class references:\n");
1209 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1210 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1212 fprintf(file," %4d: ",c->index);
1213 utf_fprint(file,c->name);
1219 fprintf(file,"hashed descriptors:\n");
1220 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1221 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1223 fprintf(file," %p: ",c->parseddesc.any);
1224 utf_fprint(file,c->desc);
1230 fprintf(file,"descriptors:\n");
1231 if (pool->descriptors) {
1232 pos = pool->descriptors;
1233 size = pool->descriptors_next - pool->descriptors;
1234 fprintf(file," size: %d bytes\n",size);
1236 if (pool->descriptor_kind) {
1237 kind = pool->descriptor_kind;
1239 while (pos < (pool->descriptors + size)) {
1240 fprintf(file," %p: ",pos);
1243 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1244 pos += sizeof(typedesc);
1247 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1248 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1249 pos += sizeof(methoddesc) - sizeof(typedesc);
1252 fprintf(file,"INVALID KIND");
1258 while (size >= sizeof(voidptr)) {
1259 fprintf(file," %p\n",*((voidptr*)pos));
1260 pos += sizeof(voidptr);
1261 size -= sizeof(voidptr);
1266 fprintf(file,"==========================================================\n");
1270 * These are local overrides for various environment variables in Emacs.
1271 * Please do not remove this and leave it at the end of the file, where
1272 * Emacs will automagically detect them.
1273 * ---------------------------------------------------------------------
1276 * indent-tabs-mode: t
1280 * vim:noexpandtab:sw=4:ts=4: