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 3380 2005-10-06 13:48:16Z 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 */
553 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
554 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
559 if (!descriptor_pool_add_class(pool,name))
563 d->paramslots = argcount;
566 *paramslots = argcount;
572 /* descriptor_pool_create_classrefs ********************************************
574 Create a table containing all the classrefs which were added to the pool
577 pool.............the descriptor_pool
580 *count...........if count is non-NULL, this is set to the number
581 of classrefs in the table
584 a pointer to the constant_classref table
586 *******************************************************************************/
589 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
593 classref_hash_entry *c;
594 constant_classref *ref;
596 DESCRIPTOR_ASSERT(pool);
598 nclasses = pool->classrefhash.entries;
599 pool->classrefs = MNEW(constant_classref,nclasses);
601 /* fill the constant_classref structs */
603 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
604 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
606 ref = pool->classrefs + c->index;
607 CLASSREF_INIT(*ref, pool->referer, c->name);
615 return pool->classrefs;
619 /* descriptor_pool_lookup_classref *********************************************
621 Return the constant_classref for the given class name
624 pool.............the descriptor_pool
625 classname........name of the class to look up
628 a pointer to the constant_classref, or
629 NULL if an exception has been thrown
631 *******************************************************************************/
634 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
637 classref_hash_entry *c;
639 DESCRIPTOR_ASSERT(pool);
640 DESCRIPTOR_ASSERT(pool->classrefs);
641 DESCRIPTOR_ASSERT(classname);
643 key = utf_hashkey(classname->text, classname->blength);
644 slot = key & (pool->classrefhash.size - 1);
645 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
648 if (c->name == classname)
649 return pool->classrefs + c->index;
653 *exceptionptr = new_internalerror("Class reference not found in descriptor pool");
658 /* descriptor_pool_alloc_parsed_descriptors ************************************
660 Allocate space for the parsed descriptors
663 pool.............the descriptor_pool
666 This function must be called after all descriptors have been added
667 with descriptor_pool_add.
669 *******************************************************************************/
672 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
676 DESCRIPTOR_ASSERT(pool);
678 /* TWISTI: paramcount + 1: we don't know if the method is static or */
679 /* not, i have no better solution yet. */
682 pool->fieldcount * sizeof(typedesc) +
683 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
684 pool->paramcount * sizeof(typedesc) +
685 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
687 pool->descriptorsize = size;
689 pool->descriptors = MNEW(u1, size);
690 pool->descriptors_next = pool->descriptors;
693 size = pool->fieldcount + pool->methodcount;
695 pool->descriptor_kind = DMNEW(u1, size);
696 pool->descriptor_kind_next = pool->descriptor_kind;
701 /* descriptor_pool_parse_field_descriptor **************************************
703 Parse the given field descriptor
706 pool.............the descriptor_pool
707 desc.............the field descriptor
710 a pointer to the parsed field descriptor, or
711 NULL if an exception has been thrown
714 descriptor_pool_alloc_parsed_descriptors must be called (once)
715 before this function is used.
717 *******************************************************************************/
720 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
723 descriptor_hash_entry *d;
726 DESCRIPTOR_ASSERT(pool);
727 DESCRIPTOR_ASSERT(pool->descriptors);
728 DESCRIPTOR_ASSERT(pool->descriptors_next);
730 /* lookup the descriptor in the hashtable */
732 key = utf_hashkey(desc->text, desc->blength);
733 slot = key & (pool->descriptorhash.size - 1);
734 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
737 if (d->desc == desc) {
739 if (d->parseddesc.fd)
740 return d->parseddesc.fd;
746 DESCRIPTOR_ASSERT(d);
748 if (desc->text[0] == '(') {
749 *exceptionptr = new_classformaterror(pool->referer,
750 "Method descriptor used in field reference");
754 td = (typedesc *) pool->descriptors_next;
755 pool->descriptors_next += sizeof(typedesc);
757 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
760 *(pool->descriptor_kind_next++) = 'f';
762 d->parseddesc.fd = td;
768 /* descriptor_pool_parse_method_descriptor *************************************
770 Parse the given method descriptor
773 pool.............the descriptor_pool
774 desc.............the method descriptor
775 mflags...........the method flags
776 thisclass........classref to the class containing the method.
777 This is ignored if mflags contains ACC_STATIC.
778 The classref is stored for inserting the 'this' argument.
781 a pointer to the parsed method descriptor, or
782 NULL if an exception has been thrown
785 descriptor_pool_alloc_parsed_descriptors must be called
786 (once) before this function is used.
788 *******************************************************************************/
791 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
792 s4 mflags,constant_classref *thisclass)
795 descriptor_hash_entry *d;
803 #ifdef DESCRIPTOR_VERBOSE
804 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
805 (void*)pool,(int)mflags,(void*)thisclass);
806 utf_fprint(stderr,desc); fprintf(stderr,")\n");
809 DESCRIPTOR_ASSERT(pool);
810 DESCRIPTOR_ASSERT(pool->descriptors);
811 DESCRIPTOR_ASSERT(pool->descriptors_next);
813 /* lookup the descriptor in the hashtable */
815 key = utf_hashkey(desc->text, desc->blength);
816 slot = key & (pool->descriptorhash.size - 1);
817 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
819 /* find an un-parsed descriptor */
823 if (!d->parseddesc.md)
828 DESCRIPTOR_ASSERT(d);
830 md = (methoddesc *) pool->descriptors_next;
831 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
833 utf_ptr = desc->text;
834 end_pos = UTF_END(desc);
836 if (*utf_ptr++ != '(') {
837 *exceptionptr = new_classformaterror(pool->referer,
838 "Field descriptor used in method reference");
844 /* count the `this' pointer */
846 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
848 td->decltype = TYPE_ADR;
850 td->classref = thisclass;
853 pool->descriptors_next += sizeof(typedesc);
858 while (*utf_ptr != ')') {
859 /* parse a parameter type */
861 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
864 if (td->type == TYPE_LONG || td->type == TYPE_DOUBLE)
868 pool->descriptors_next += sizeof(typedesc);
872 utf_ptr++; /* skip ')' */
874 /* Skip possible `this' pointer in paramtypes array to allow a possible */
875 /* memory move later in parse. */
876 /* We store the thisclass reference, so we can later correctly fill in */
877 /* the parameter slot of the 'this' argument. */
879 if (mflags == ACC_UNDEF) {
880 td->classref = thisclass;
882 pool->descriptors_next += sizeof(typedesc);
885 /* parse return type */
887 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
891 md->paramcount = paramcount;
892 md->paramslots = paramslots;
894 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
895 /* Otherwise we do this in stack analysis. */
897 if (mflags != ACC_UNDEF) {
898 if (md->paramcount > 0) {
899 /* allocate memory for params */
901 md->params = MNEW(paramdesc, md->paramcount);
904 md->params = METHODDESC_NOPARAMS;
907 /* fill the paramdesc */
908 /* md_param_alloc has to be called if md->paramcount == 0, too, so it */
909 /* can make the reservation for the Linkage Area, Return Register... */
913 /* params will be allocated later by descriptor_params_from_paramtypes */
918 *(pool->descriptor_kind_next++) = 'm';
920 d->parseddesc.md = md;
925 /* descriptor_params_from_paramtypes *******************************************
927 Create the paramdescs for a method descriptor. This function is called
928 when we know whether the method is static or not. This function may only
929 be called once for each methoddesc, and only if md->params == NULL.
932 md...............the parsed method descriptor
933 md->params MUST be NULL.
934 mflags...........the ACC_* access flags of the method. Only the
935 ACC_STATIC bit is checked.
936 The value ACC_UNDEF is NOT allowed.
939 true.............the paramdescs were created successfully
940 false............an exception has been thrown
945 *******************************************************************************/
947 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
951 DESCRIPTOR_ASSERT(md);
952 DESCRIPTOR_ASSERT(md->params == NULL);
953 DESCRIPTOR_ASSERT(mflags != ACC_UNDEF);
957 /* check for `this' pointer */
959 if (!(mflags & ACC_STATIC)) {
960 constant_classref *thisclass;
962 /* fetch class reference from reserved param slot */
963 thisclass = td[md->paramcount].classref;
964 DESCRIPTOR_ASSERT(thisclass);
966 if (md->paramcount > 0) {
967 /* shift param types by 1 argument */
968 MMOVE(td + 1, td, typedesc, md->paramcount);
971 /* fill in first argument `this' */
974 td->decltype = TYPE_ADR;
976 td->classref = thisclass;
982 /* if the method has params, process them */
984 if (md->paramcount > 0) {
985 /* allocate memory for params */
987 md->params = MNEW(paramdesc, md->paramcount);
990 md->params = METHODDESC_NOPARAMS;
993 /* fill the paramdesc */
994 /* md_param_alloc has to be called if md->paramcount == 0, too, so */
995 /* it can make the reservation for the Linkage Area, Return Register.. */
1003 /* descriptor_pool_get_parsed_descriptors **************************************
1005 Return a pointer to the block of parsed descriptors
1008 pool.............the descriptor_pool
1011 *size............if size is non-NULL, this is set to the size of the
1012 parsed descriptor block (in u1)
1015 a pointer to the block of parsed descriptors
1018 descriptor_pool_alloc_parsed_descriptors must be called (once)
1019 before this function is used.
1021 *******************************************************************************/
1024 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1026 DESCRIPTOR_ASSERT(pool);
1027 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1030 *size = pool->descriptorsize;
1032 return pool->descriptors;
1036 /* descriptor_pool_get_sizes ***************************************************
1038 Get the sizes of the class reference table and the parsed descriptors
1041 pool.............the descriptor_pool
1044 *classrefsize....set to size of the class reference table
1045 *descsize........set to size of the parsed descriptors
1048 This function may only be called after both
1049 descriptor_pool_create_classrefs, and
1050 descriptor_pool_alloc_parsed_descriptors
1053 *******************************************************************************/
1056 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1058 DESCRIPTOR_ASSERT(pool);
1059 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1060 DESCRIPTOR_ASSERT(pool->classrefs);
1061 DESCRIPTOR_ASSERT(classrefsize);
1062 DESCRIPTOR_ASSERT(descsize);
1064 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1065 *descsize = pool->descriptorsize;
1069 /* descriptor_debug_print_typedesc *********************************************
1071 Print the given typedesc to the given stream
1074 file.............stream to print to
1075 d................the parsed descriptor
1077 *******************************************************************************/
1080 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1085 fprintf(file,"(typedesc *)NULL");
1089 if (d->type == TYPE_ADDRESS) {
1091 utf_fprint(file,d->classref->name);
1093 fprintf(file,"<class=NULL>");
1096 switch (d->decltype) {
1097 case PRIMITIVETYPE_INT : ch='I'; break;
1098 case PRIMITIVETYPE_CHAR : ch='C'; break;
1099 case PRIMITIVETYPE_BYTE : ch='B'; break;
1100 case PRIMITIVETYPE_SHORT : ch='S'; break;
1101 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1102 case PRIMITIVETYPE_LONG : ch='J'; break;
1103 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1104 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1105 case PRIMITIVETYPE_VOID : ch='V'; break;
1111 fprintf(file,"[%d]",d->arraydim);
1114 /* descriptor_debug_print_paramdesc ********************************************
1116 Print the given paramdesc to the given stream
1119 file.............stream to print to
1120 d................the parameter descriptor
1122 *******************************************************************************/
1125 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1128 fprintf(file,"(paramdesc *)NULL");
1133 fprintf(file,"<m%d>",d->regoff);
1136 fprintf(file,"<r%d>",d->regoff);
1140 /* descriptor_debug_print_methoddesc *******************************************
1142 Print the given methoddesc to the given stream
1145 file.............stream to print to
1146 d................the parsed descriptor
1148 *******************************************************************************/
1151 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1156 fprintf(file,"(methoddesc *)NULL");
1161 for (i=0; i<d->paramcount; ++i) {
1164 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1166 descriptor_debug_print_paramdesc(file,d->params + i);
1169 if (d->params == METHODDESC_NOPARAMS)
1170 fputs("<NOPARAMS>",file);
1172 descriptor_debug_print_typedesc(file,&(d->returntype));
1175 /* descriptor_pool_debug_dump **************************************************
1177 Print the state of the descriptor_pool to the given stream
1180 pool.............the descriptor_pool
1181 file.............stream to print to
1183 *******************************************************************************/
1186 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1193 fprintf(file,"======[descriptor_pool for ");
1194 utf_fprint(file,pool->referer->name);
1195 fprintf(file,"]======\n");
1197 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1198 fprintf(file,"methodcount: %d\n",pool->methodcount);
1199 fprintf(file,"paramcount: %d\n",pool->paramcount);
1200 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1201 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1202 fprintf(file,"classrefsize: %d bytes\n",
1203 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1205 fprintf(file,"class references:\n");
1206 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1207 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1209 fprintf(file," %4d: ",c->index);
1210 utf_fprint(file,c->name);
1216 fprintf(file,"hashed descriptors:\n");
1217 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1218 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1220 fprintf(file," %p: ",c->parseddesc.any);
1221 utf_fprint(file,c->desc);
1227 fprintf(file,"descriptors:\n");
1228 if (pool->descriptors) {
1229 pos = pool->descriptors;
1230 size = pool->descriptors_next - pool->descriptors;
1231 fprintf(file," size: %d bytes\n",size);
1233 if (pool->descriptor_kind) {
1234 kind = pool->descriptor_kind;
1236 while (pos < (pool->descriptors + size)) {
1237 fprintf(file," %p: ",pos);
1240 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1241 pos += sizeof(typedesc);
1244 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1245 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1246 pos += sizeof(methoddesc) - sizeof(typedesc);
1249 fprintf(file,"INVALID KIND");
1255 while (size >= sizeof(voidptr)) {
1256 fprintf(file," %p\n",*((voidptr*)pos));
1257 pos += sizeof(voidptr);
1258 size -= sizeof(voidptr);
1263 fprintf(file,"==========================================================\n");
1267 * These are local overrides for various environment variables in Emacs.
1268 * Please do not remove this and leave it at the end of the file, where
1269 * Emacs will automagically detect them.
1270 * ---------------------------------------------------------------------
1273 * indent-tabs-mode: t
1277 * vim:noexpandtab:sw=4:ts=4: