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
36 #include "mm/memory.h"
38 #include "vm/exceptions.h"
39 #include "vm/jit_interface.h"
40 #include "vm/primitive.h"
43 #include "vmcore/descriptor.h"
44 #include "vmcore/options.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 int descriptor_to_basic_type(utf *descriptor)
148 assert(descriptor->blength >= 1);
150 switch (descriptor->text[0]) {
172 vm_abort("descriptor_to_basic_type: invalid type %c",
173 descriptor->text[0]);
176 /* keep the compiler happy */
182 /* descriptor_typesize *********************************************************
184 Return the size in bytes needed for the given type.
187 td..............typedesc describing the type
192 *******************************************************************************/
194 int descriptor_typesize(typedesc *td)
208 return SIZEOF_VOID_P;
211 vm_abort("descriptor_typesize: invalid type %d", td->type);
214 /* keep the compiler happy */
220 /* name_from_descriptor ********************************************************
222 Return the class name indicated by the given descriptor
223 (Internally used helper function)
226 c................class containing the descriptor
227 utf_ptr..........first character of descriptor
228 end_ptr..........first character after the end of the string
229 mode.............a combination (binary or) of the following flags:
231 (Flags marked with * are the default settings.)
233 How to handle "V" descriptors:
235 * DESCRIPTOR_VOID.....handle it like other primitive types
236 DESCRIPTOR_NOVOID...treat it as an error
238 How to deal with extra characters after the end of the
241 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
242 DESCRIPTOR_CHECKEND.....treat them as an error
245 *next............if non-NULL, *next is set to the first character after
246 the descriptor. (Undefined if an error occurs.)
247 *name............set to the utf name of the class
250 true.............descriptor parsed successfully
251 false............an exception has been thrown
253 *******************************************************************************/
255 #define DESCRIPTOR_VOID 0 /* default */
256 #define DESCRIPTOR_NOVOID 0x0040
257 #define DESCRIPTOR_NOCHECKEND 0 /* default */
258 #define DESCRIPTOR_CHECKEND 0x1000
261 name_from_descriptor(classinfo *c,
262 char *utf_ptr, char *end_ptr,
263 char **next, int mode, utf **name)
265 char *start = utf_ptr;
274 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
276 if (mode & DESCRIPTOR_CHECKEND)
277 error |= (utf_ptr != end_ptr);
280 if (next) *next = utf_ptr;
284 if (mode & DESCRIPTOR_NOVOID)
302 *name = utf_new(start, utf_ptr - start);
307 exceptions_throw_classformaterror(c, "Invalid descriptor");
312 /* descriptor_to_typedesc ******************************************************
314 Parse the given type descriptor and fill a typedesc struct
315 (Internally used helper function)
318 pool.............the descriptor pool
319 utf_ptr..........points to first character of type descriptor
320 end_pos..........points after last character of the whole descriptor
323 *next............set to next character after type descriptor
324 *d...............filled with parsed information
327 true.............parsing succeeded
328 false............an exception has been thrown
330 *******************************************************************************/
333 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
334 char **next, typedesc *td)
338 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
342 /* a reference type */
344 td->decltype = TYPE_ADR;
346 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
348 td->classref = descriptor_pool_lookup_classref(pool, name);
351 /* a primitive type */
354 td->decltype = PRIMITIVETYPE_BYTE;
358 td->decltype = PRIMITIVETYPE_CHAR;
362 td->decltype = PRIMITIVETYPE_SHORT;
366 td->decltype = PRIMITIVETYPE_BOOLEAN;
370 td->decltype = PRIMITIVETYPE_INT;
374 td->decltype = PRIMITIVETYPE_DOUBLE;
378 td->decltype = PRIMITIVETYPE_FLOAT;
382 td->decltype = PRIMITIVETYPE_LONG;
386 td->decltype = PRIMITIVETYPE_VOID;
387 td->type = TYPE_VOID;
401 /* descriptor_pool_new *********************************************************
403 Allocate a new descriptor_pool
406 referer..........class for which to create the pool
409 a pointer to the new descriptor_pool
411 *******************************************************************************/
414 descriptor_pool_new(classinfo *referer)
416 descriptor_pool *pool;
420 pool = DNEW(descriptor_pool);
423 pool->referer = referer;
424 pool->fieldcount = 0;
425 pool->methodcount = 0;
426 pool->paramcount = 0;
427 pool->descriptorsize = 0;
428 pool->descriptors = NULL;
429 pool->descriptors_next = NULL;
430 pool->classrefs = NULL;
431 pool->descriptor_kind = NULL;
432 pool->descriptor_kind_next = NULL;
434 hashsize = CLASSREFHASH_INIT_SIZE;
435 pool->classrefhash.size = hashsize;
436 pool->classrefhash.entries = 0;
437 pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
438 for (slot=0; slot<hashsize; ++slot)
439 pool->classrefhash.ptr[slot] = NULL;
441 hashsize = DESCRIPTORHASH_INIT_SIZE;
442 pool->descriptorhash.size = hashsize;
443 pool->descriptorhash.entries = 0;
444 pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
445 for (slot=0; slot<hashsize; ++slot)
446 pool->descriptorhash.ptr[slot] = NULL;
452 /* descriptor_pool_add_class ***************************************************
454 Add the given class reference to the pool
457 pool.............the descriptor_pool
458 name.............the class reference to add
461 true.............reference has been added
462 false............an exception has been thrown
464 *******************************************************************************/
467 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
470 classref_hash_entry *c;
475 #ifdef DESCRIPTOR_VERBOSE
476 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
477 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
480 /* find a place in the hashtable */
482 key = utf_hashkey(name->text, name->blength);
483 slot = key & (pool->classrefhash.size - 1);
484 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
488 return true; /* already stored */
492 /* check if the name is a valid classname */
494 if (!is_valid_name(name->text,UTF_END(name))) {
495 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
496 return false; /* exception */
499 /* XXX check maximum array dimension */
501 c = DNEW(classref_hash_entry);
503 c->index = pool->classrefhash.entries++;
504 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
505 pool->classrefhash.ptr[slot] = c;
511 /* descriptor_pool_add *********************************************************
513 Check the given descriptor and add it to the pool
516 pool.............the descriptor_pool
517 desc.............the descriptor to add. Maybe a field or method desc.
520 *paramslots......if non-NULL, set to the number of parameters.
521 LONG and DOUBLE are counted twice
524 true.............descriptor has been added
525 false............an exception has been thrown
527 *******************************************************************************/
530 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
533 descriptor_hash_entry *d;
539 #ifdef DESCRIPTOR_VERBOSE
540 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
541 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
547 /* find a place in the hashtable */
549 key = utf_hashkey(desc->text, desc->blength);
550 slot = key & (pool->descriptorhash.size - 1);
551 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
553 /* Save all method descriptors in the hashtable, since the parsed */
554 /* descriptor may vary between differenf methods (static vs. non-static). */
556 utf_ptr = desc->text;
558 if (*utf_ptr != '(') {
560 if (d->desc == desc) {
562 *paramslots = d->paramslots;
563 return true; /* already stored */
569 /* add the descriptor to the pool */
571 d = DNEW(descriptor_hash_entry);
573 d->parseddesc.any = NULL;
574 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
575 pool->descriptorhash.ptr[slot] = d;
577 /* now check the descriptor */
579 end_pos = UTF_END(desc);
581 if (*utf_ptr == '(') {
582 /* a method descriptor */
587 /* check arguments */
589 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
592 /* We cannot count the `this' argument here because
593 * we don't know if the method is static. */
595 if (*utf_ptr == 'J' || *utf_ptr == 'D')
600 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
601 DESCRIPTOR_NOVOID, &name))
605 if (!descriptor_pool_add_class(pool, name))
609 if (utf_ptr == end_pos) {
610 exceptions_throw_classformaterror(pool->referer,
611 "Missing ')' in method descriptor");
615 utf_ptr++; /* skip ')' */
617 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
618 DESCRIPTOR_CHECKEND, &name))
622 if (!descriptor_pool_add_class(pool,name))
625 if (argcount > 255) {
626 exceptions_throw_classformaterror(pool->referer,
627 "Too many arguments in signature");
632 /* a field descriptor */
636 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
637 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
642 if (!descriptor_pool_add_class(pool,name))
646 d->paramslots = argcount;
649 *paramslots = argcount;
655 /* descriptor_pool_create_classrefs ********************************************
657 Create a table containing all the classrefs which were added to the pool
660 pool.............the descriptor_pool
663 *count...........if count is non-NULL, this is set to the number
664 of classrefs in the table
667 a pointer to the constant_classref table
669 *******************************************************************************/
672 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
676 classref_hash_entry *c;
677 constant_classref *ref;
681 nclasses = pool->classrefhash.entries;
682 pool->classrefs = MNEW(constant_classref,nclasses);
684 /* fill the constant_classref structs */
686 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
687 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
689 ref = pool->classrefs + c->index;
690 CLASSREF_INIT(*ref, pool->referer, c->name);
698 return pool->classrefs;
702 /* descriptor_pool_lookup_classref *********************************************
704 Return the constant_classref for the given class name
707 pool.............the descriptor_pool
708 classname........name of the class to look up
711 a pointer to the constant_classref, or
712 NULL if an exception has been thrown
714 *******************************************************************************/
717 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
720 classref_hash_entry *c;
723 assert(pool->classrefs);
726 key = utf_hashkey(classname->text, classname->blength);
727 slot = key & (pool->classrefhash.size - 1);
728 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
731 if (c->name == classname)
732 return pool->classrefs + c->index;
736 exceptions_throw_internalerror("Class reference not found in descriptor pool");
741 /* descriptor_pool_alloc_parsed_descriptors ************************************
743 Allocate space for the parsed descriptors
746 pool.............the descriptor_pool
749 This function must be called after all descriptors have been added
750 with descriptor_pool_add.
752 *******************************************************************************/
755 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
761 /* TWISTI: paramcount + 1: we don't know if the method is static or */
762 /* not, i have no better solution yet. */
765 pool->fieldcount * sizeof(typedesc) +
766 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
767 pool->paramcount * sizeof(typedesc) +
768 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
770 pool->descriptorsize = size;
772 pool->descriptors = MNEW(u1, size);
773 pool->descriptors_next = pool->descriptors;
776 size = pool->fieldcount + pool->methodcount;
778 pool->descriptor_kind = DMNEW(u1, size);
779 pool->descriptor_kind_next = pool->descriptor_kind;
784 /* descriptor_pool_parse_field_descriptor **************************************
786 Parse the given field descriptor
789 pool.............the descriptor_pool
790 desc.............the field descriptor
793 a pointer to the parsed field descriptor, or
794 NULL if an exception has been thrown
797 descriptor_pool_alloc_parsed_descriptors must be called (once)
798 before this function is used.
800 *******************************************************************************/
803 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
806 descriptor_hash_entry *d;
810 assert(pool->descriptors);
811 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];
820 if (d->desc == desc) {
822 if (d->parseddesc.fd)
823 return d->parseddesc.fd;
831 if (desc->text[0] == '(') {
832 exceptions_throw_classformaterror(pool->referer,
833 "Method descriptor used in field reference");
837 td = (typedesc *) pool->descriptors_next;
838 pool->descriptors_next += sizeof(typedesc);
840 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
843 *(pool->descriptor_kind_next++) = 'f';
845 d->parseddesc.fd = td;
851 /* descriptor_pool_parse_method_descriptor *************************************
853 Parse the given method descriptor
856 pool.............the descriptor_pool
857 desc.............the method descriptor
858 mflags...........the method flags
859 thisclass........classref to the class containing the method.
860 This is ignored if mflags contains ACC_STATIC.
861 The classref is stored for inserting the 'this' argument.
864 a pointer to the parsed method descriptor, or
865 NULL if an exception has been thrown
868 descriptor_pool_alloc_parsed_descriptors must be called
869 (once) before this function is used.
871 *******************************************************************************/
874 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
875 s4 mflags,constant_classref *thisclass)
878 descriptor_hash_entry *d;
886 #ifdef DESCRIPTOR_VERBOSE
887 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
888 (void*)pool,(int)mflags,(void*)thisclass);
889 utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
893 assert(pool->descriptors);
894 assert(pool->descriptors_next);
896 /* check that it is a method descriptor */
898 if (desc->text[0] != '(') {
899 exceptions_throw_classformaterror(pool->referer,
900 "Field descriptor used in method reference");
904 /* lookup the descriptor in the hashtable */
906 key = utf_hashkey(desc->text, desc->blength);
907 slot = key & (pool->descriptorhash.size - 1);
908 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
910 /* find an un-parsed descriptor */
914 if (!d->parseddesc.md)
921 md = (methoddesc *) pool->descriptors_next;
922 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
924 utf_ptr = desc->text + 1; /* skip '(' */
925 end_pos = UTF_END(desc);
929 /* count the `this' pointer */
931 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
933 td->decltype = TYPE_ADR;
935 td->classref = thisclass;
938 pool->descriptors_next += sizeof(typedesc);
943 while (*utf_ptr != ')') {
944 /* parse a parameter type */
946 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
949 if (IS_2_WORD_TYPE(td->type))
953 pool->descriptors_next += sizeof(typedesc);
957 utf_ptr++; /* skip ')' */
959 /* Skip possible `this' pointer in paramtypes array to allow a possible */
960 /* memory move later in parse. */
961 /* We store the thisclass reference, so we can later correctly fill in */
962 /* the parameter slot of the 'this' argument. */
964 if (mflags == ACC_UNDEF) {
965 td->classref = thisclass;
967 pool->descriptors_next += sizeof(typedesc);
970 /* parse return type */
972 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
976 md->paramcount = paramcount;
977 md->paramslots = paramslots;
979 /* If mflags != ACC_UNDEF we parse a real loaded method, so do
980 param prealloc. Otherwise we do this in stack analysis. */
982 if (mflags != ACC_UNDEF) {
983 if (md->paramcount > 0) {
984 /* allocate memory for params */
986 md->params = MNEW(paramdesc, md->paramcount);
989 md->params = METHODDESC_NOPARAMS;
992 /* fill the paramdesc */
993 /* md_param_alloc has to be called if md->paramcount == 0,
994 too, so it can make the reservation for the Linkage Area,
995 Return Register... */
997 #if defined(ENABLE_JIT)
998 # if defined(ENABLE_INTRP)
1002 /* As builtin-functions are native functions, we have
1003 to pre-allocate for the native ABI. */
1005 if (mflags & ACC_METHOD_BUILTIN)
1006 md_param_alloc_native(md);
1013 /* params will be allocated later by
1014 descriptor_params_from_paramtypes if necessary */
1019 *(pool->descriptor_kind_next++) = 'm';
1021 d->parseddesc.md = md;
1026 /* descriptor_params_from_paramtypes *******************************************
1028 Create the paramdescs for a method descriptor. This function is called
1029 when we know whether the method is static or not. This function may only
1030 be called once for each methoddesc, and only if md->params == NULL.
1033 md...............the parsed method descriptor
1034 md->params MUST be NULL.
1035 mflags...........the ACC_* access flags of the method. Only the
1036 ACC_STATIC bit is checked.
1037 The value ACC_UNDEF is NOT allowed.
1040 true.............the paramdescs were created successfully
1041 false............an exception has been thrown
1046 *******************************************************************************/
1048 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1053 assert(md->params == NULL);
1054 assert(mflags != ACC_UNDEF);
1056 td = md->paramtypes;
1058 /* check for `this' pointer */
1060 if (!(mflags & ACC_STATIC)) {
1061 constant_classref *thisclass;
1063 /* fetch class reference from reserved param slot */
1064 thisclass = td[md->paramcount].classref;
1067 if (md->paramcount > 0) {
1068 /* shift param types by 1 argument */
1069 MMOVE(td + 1, td, typedesc, md->paramcount);
1072 /* fill in first argument `this' */
1074 td->type = TYPE_ADR;
1075 td->decltype = TYPE_ADR;
1077 td->classref = thisclass;
1083 /* if the method has params, process them */
1085 if (md->paramcount > 0) {
1086 /* allocate memory for params */
1088 md->params = MNEW(paramdesc, md->paramcount);
1091 md->params = METHODDESC_NOPARAMS;
1094 /* fill the paramdesc */
1095 /* md_param_alloc has to be called if md->paramcount == 0, too, so
1096 it can make the reservation for the Linkage Area, Return
1099 #if defined(ENABLE_JIT)
1100 # if defined(ENABLE_INTRP)
1104 /* As builtin-functions are native functions, we have to
1105 pre-allocate for the native ABI. */
1107 if (mflags & ACC_METHOD_BUILTIN)
1108 md_param_alloc_native(md);
1118 /* descriptor_pool_get_parsed_descriptors **************************************
1120 Return a pointer to the block of parsed descriptors
1123 pool.............the descriptor_pool
1126 *size............if size is non-NULL, this is set to the size of the
1127 parsed descriptor block (in u1)
1130 a pointer to the block of parsed descriptors
1133 descriptor_pool_alloc_parsed_descriptors must be called (once)
1134 before this function is used.
1136 *******************************************************************************/
1139 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
1142 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1145 *size = pool->descriptorsize;
1147 return pool->descriptors;
1151 /* descriptor_pool_get_sizes ***************************************************
1153 Get the sizes of the class reference table and the parsed descriptors
1156 pool.............the descriptor_pool
1159 *classrefsize....set to size of the class reference table
1160 *descsize........set to size of the parsed descriptors
1163 This function may only be called after both
1164 descriptor_pool_create_classrefs, and
1165 descriptor_pool_alloc_parsed_descriptors
1168 *******************************************************************************/
1171 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1174 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1175 assert(pool->classrefs);
1176 assert(classrefsize);
1179 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1180 *descsize = pool->descriptorsize;
1184 /****************************************************************************/
1186 /****************************************************************************/
1189 /* descriptor_debug_print_typedesc *********************************************
1191 Print the given typedesc to the given stream
1194 file.............stream to print to
1195 d................the parsed descriptor
1197 *******************************************************************************/
1200 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1205 fprintf(file,"(typedesc *)NULL");
1209 if (d->type == TYPE_ADR) {
1211 utf_fprint_printable_ascii(file,d->classref->name);
1213 fprintf(file,"<class=NULL>");
1216 switch (d->decltype) {
1217 case PRIMITIVETYPE_INT : ch='I'; break;
1218 case PRIMITIVETYPE_CHAR : ch='C'; break;
1219 case PRIMITIVETYPE_BYTE : ch='B'; break;
1220 case PRIMITIVETYPE_SHORT : ch='S'; break;
1221 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1222 case PRIMITIVETYPE_LONG : ch='J'; break;
1223 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1224 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1225 case PRIMITIVETYPE_VOID : ch='V'; break;
1231 fprintf(file,"[%d]",d->arraydim);
1234 /* descriptor_debug_print_paramdesc ********************************************
1236 Print the given paramdesc to the given stream
1239 file.............stream to print to
1240 d................the parameter descriptor
1242 *******************************************************************************/
1245 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1248 fprintf(file,"(paramdesc *)NULL");
1253 fprintf(file,"<m%d>",d->regoff);
1256 fprintf(file,"<r%d>",d->regoff);
1260 /* descriptor_debug_print_methoddesc *******************************************
1262 Print the given methoddesc to the given stream
1265 file.............stream to print to
1266 d................the parsed descriptor
1268 *******************************************************************************/
1271 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1276 fprintf(file,"(methoddesc *)NULL");
1281 for (i=0; i<d->paramcount; ++i) {
1284 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1286 descriptor_debug_print_paramdesc(file,d->params + i);
1289 if (d->params == METHODDESC_NOPARAMS)
1290 fputs("<NOPARAMS>",file);
1292 descriptor_debug_print_typedesc(file,&(d->returntype));
1295 /* descriptor_pool_debug_dump **************************************************
1297 Print the state of the descriptor_pool to the given stream
1300 pool.............the descriptor_pool
1301 file.............stream to print to
1303 *******************************************************************************/
1306 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1313 fprintf(file,"======[descriptor_pool for ");
1314 utf_fprint_printable_ascii(file,pool->referer->name);
1315 fprintf(file,"]======\n");
1317 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1318 fprintf(file,"methodcount: %d\n",pool->methodcount);
1319 fprintf(file,"paramcount: %d\n",pool->paramcount);
1320 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1321 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1322 fprintf(file,"classrefsize: %d bytes\n",
1323 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1325 fprintf(file,"class references:\n");
1326 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1327 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1329 fprintf(file," %4d: ",c->index);
1330 utf_fprint_printable_ascii(file,c->name);
1336 fprintf(file,"hashed descriptors:\n");
1337 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1338 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1340 fprintf(file," %p: ",c->parseddesc.any);
1341 utf_fprint_printable_ascii(file,c->desc);
1347 fprintf(file,"descriptors:\n");
1348 if (pool->descriptors) {
1349 pos = pool->descriptors;
1350 size = pool->descriptors_next - pool->descriptors;
1351 fprintf(file," size: %d bytes\n",size);
1353 if (pool->descriptor_kind) {
1354 kind = pool->descriptor_kind;
1356 while (pos < (pool->descriptors + size)) {
1357 fprintf(file," %p: ",pos);
1360 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1361 pos += sizeof(typedesc);
1364 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1365 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1366 pos += sizeof(methoddesc) - sizeof(typedesc);
1369 fprintf(file,"INVALID KIND");
1375 while (size >= sizeof(voidptr)) {
1376 fprintf(file," %p\n",*((voidptr*)pos));
1377 pos += sizeof(voidptr);
1378 size -= sizeof(voidptr);
1383 fprintf(file,"==========================================================\n");
1385 #endif /* !defined(NDEBUG) */
1388 * These are local overrides for various environment variables in Emacs.
1389 * Please do not remove this and leave it at the end of the file, where
1390 * Emacs will automagically detect them.
1391 * ---------------------------------------------------------------------
1394 * indent-tabs-mode: t
1398 * vim:noexpandtab:sw=4:ts=4: