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
31 $Id: descriptor.c 2668 2005-06-13 14:26:55Z twisti $
41 #include "mm/memory.h"
42 #include "vm/descriptor.h"
43 #include "vm/exceptions.h"
44 #include "vm/resolve.h"
45 #include "vm/stringlocal.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 */
78 /****************************************************************************/
80 /****************************************************************************/
83 #define DESCRIPTOR_DEBUG
86 #ifdef DESCRIPTOR_DEBUG
87 #define DESCRIPTOR_ASSERT(cond) assert(cond)
89 #define DESCRIPTOR_ASSERT(cond)
92 /* name_from_descriptor ********************************************************
94 Return the class name indicated by the given descriptor
95 (Internally used helper function)
98 c................class containing the descriptor
99 utf_ptr..........first character of descriptor
100 end_ptr..........first character after the end of the string
101 mode.............a combination (binary or) of the following flags:
103 (Flags marked with * are the default settings.)
105 How to handle "V" descriptors:
107 * DESCRIPTOR_VOID.....handle it like other primitive types
108 DESCRIPTOR_NOVOID...treat it as an error
110 How to deal with extra characters after the end of the
113 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
114 DESCRIPTOR_CHECKEND.....treat them as an error
117 *next............if non-NULL, *next is set to the first character after
118 the descriptor. (Undefined if an error occurs.)
119 *name............set to the utf name of the class
122 true.............descriptor parsed successfully
123 false............an exception has been thrown
125 *******************************************************************************/
127 #define DESCRIPTOR_VOID 0 /* default */
128 #define DESCRIPTOR_NOVOID 0x0040
129 #define DESCRIPTOR_NOCHECKEND 0 /* default */
130 #define DESCRIPTOR_CHECKEND 0x1000
133 name_from_descriptor(classinfo *c,
134 char *utf_ptr, char *end_ptr,
135 char **next, int mode, utf **name)
137 char *start = utf_ptr;
140 DESCRIPTOR_ASSERT(c);
141 DESCRIPTOR_ASSERT(utf_ptr);
142 DESCRIPTOR_ASSERT(end_ptr);
143 DESCRIPTOR_ASSERT(name);
146 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
148 if (mode & DESCRIPTOR_CHECKEND)
149 error |= (utf_ptr != end_ptr);
152 if (next) *next = utf_ptr;
156 if (mode & DESCRIPTOR_NOVOID)
174 *name = utf_new(start, utf_ptr - start);
179 *exceptionptr = new_classformaterror(c,"invalid descriptor");
184 /* descriptor_to_typedesc ******************************************************
186 Parse the given type descriptor and fill a typedesc struct
187 (Internally used helper function)
190 pool.............the descriptor pool
191 utf_ptr..........points to first character of type descriptor
192 end_pos..........points after last character of the whole descriptor
195 *next............set to next character after type descriptor
196 *d...............filled with parsed information
199 true.............parsing succeeded
200 false............an exception has been thrown
202 *******************************************************************************/
205 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
206 char **next, typedesc *td)
210 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
214 /* a reference type */
215 td->type = TYPE_ADDRESS;
216 td->decltype = TYPE_ADDRESS;
218 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
220 td->classref = descriptor_pool_lookup_classref(pool, name);
223 /* a primitive type */
226 td->decltype = PRIMITIVETYPE_BYTE;
230 td->decltype = PRIMITIVETYPE_CHAR;
234 td->decltype = PRIMITIVETYPE_SHORT;
238 td->decltype = PRIMITIVETYPE_BOOLEAN;
242 td->decltype = PRIMITIVETYPE_INT;
246 td->decltype = PRIMITIVETYPE_DOUBLE;
247 td->type = TYPE_DOUBLE;
250 td->decltype = PRIMITIVETYPE_FLOAT;
251 td->type = TYPE_FLOAT;
254 td->decltype = PRIMITIVETYPE_LONG;
255 td->type = TYPE_LONG;
258 td->decltype = PRIMITIVETYPE_VOID;
259 td->type = TYPE_VOID;
262 DESCRIPTOR_ASSERT(false);
273 /* descriptor_pool_new *********************************************************
275 Allocate a new descriptor_pool
278 referer..........class for which to create the pool
281 a pointer to the new descriptor_pool
283 *******************************************************************************/
286 descriptor_pool_new(classinfo *referer)
288 descriptor_pool *pool;
292 pool = DNEW(descriptor_pool);
293 DESCRIPTOR_ASSERT(pool);
295 pool->referer = referer;
296 pool->fieldcount = 0;
297 pool->methodcount = 0;
298 pool->paramcount = 0;
299 pool->descriptorsize = 0;
300 pool->descriptors = NULL;
301 pool->descriptors_next = NULL;
302 pool->classrefs = NULL;
303 pool->descriptor_kind = NULL;
304 pool->descriptor_kind_next = NULL;
306 hashsize = CLASSREFHASH_INIT_SIZE;
307 pool->classrefhash.size = hashsize;
308 pool->classrefhash.entries = 0;
309 pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
310 for (slot=0; slot<hashsize; ++slot)
311 pool->classrefhash.ptr[slot] = NULL;
313 hashsize = DESCRIPTORHASH_INIT_SIZE;
314 pool->descriptorhash.size = hashsize;
315 pool->descriptorhash.entries = 0;
316 pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
317 for (slot=0; slot<hashsize; ++slot)
318 pool->descriptorhash.ptr[slot] = NULL;
324 /* descriptor_pool_add_class ***************************************************
326 Add the given class reference to the pool
329 pool.............the descriptor_pool
330 name.............the class reference to add
333 true.............reference has been added
334 false............an exception has been thrown
336 *******************************************************************************/
339 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
342 classref_hash_entry *c;
344 DESCRIPTOR_ASSERT(pool);
345 DESCRIPTOR_ASSERT(name);
347 /* find a place in the hashtable */
349 key = utf_hashkey(name->text, name->blength);
350 slot = key & (pool->classrefhash.size - 1);
351 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
355 return true; /* already stored */
359 /* check if the name is a valid classname */
361 if (!is_valid_name(name->text,UTF_END(name))) {
362 *exceptionptr = new_classformaterror(pool->referer,
363 "Invalid class name");
364 return false; /* exception */
367 /* XXX check maximum array dimension */
369 c = DNEW(classref_hash_entry);
371 c->index = pool->classrefhash.entries++;
372 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
373 pool->classrefhash.ptr[slot] = c;
379 /* descriptor_pool_add *********************************************************
381 Check the given descriptor and add it to the pool
384 pool.............the descriptor_pool
385 desc.............the descriptor to add. Maybe a field or method desc.
388 *paramslots......if non-NULL, set to the number of parameters.
389 LONG and DOUBLE are counted twice
392 true.............descriptor has been added
393 false............an exception has been thrown
395 *******************************************************************************/
398 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
401 descriptor_hash_entry *d;
407 DESCRIPTOR_ASSERT(pool);
408 DESCRIPTOR_ASSERT(desc);
410 /* find a place in the hashtable */
412 key = utf_hashkey(desc->text, desc->blength);
413 slot = key & (pool->descriptorhash.size - 1);
414 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
416 /* Save all method descriptors in the hashtable, since the parsed */
417 /* descriptor may vary between differenf methods (static vs. non-static). */
419 utf_ptr = desc->text;
421 if (*utf_ptr != '(') {
423 if (d->desc == desc) {
425 *paramslots = d->paramslots;
426 return true; /* already stored */
432 /* add the descriptor to the pool */
434 d = DNEW(descriptor_hash_entry);
436 d->parseddesc.any = NULL;
437 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
438 pool->descriptorhash.ptr[slot] = d;
440 /* now check the descriptor */
442 end_pos = UTF_END(desc);
444 if (*utf_ptr == '(') {
445 /* a method descriptor */
450 /* check arguments */
452 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
455 /* We cannot count the `this' argument here because
456 * we don't know if the method is static. */
458 if (*utf_ptr == 'J' || *utf_ptr == 'D')
463 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
464 DESCRIPTOR_NOVOID, &name))
468 descriptor_pool_add_class(pool, name);
471 if (utf_ptr == end_pos) {
472 *exceptionptr = new_classformaterror(pool->referer,"Missing ')' in method descriptor");
476 utf_ptr++; /* skip ')' */
478 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
479 DESCRIPTOR_CHECKEND, &name))
483 descriptor_pool_add_class(pool,name);
485 if (argcount > 255) {
487 new_classformaterror(pool->referer,"Too many arguments in signature");
492 /* a field descriptor */
495 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
496 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
501 descriptor_pool_add_class(pool,name);
504 d->paramslots = argcount;
507 *paramslots = argcount;
513 /* descriptor_pool_create_classrefs ********************************************
515 Create a table containing all the classrefs which were added to the pool
518 pool.............the descriptor_pool
521 *count...........if count is non-NULL, this is set to the number
522 of classrefs in the table
525 a pointer to the constant_classref table
527 *******************************************************************************/
530 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
534 classref_hash_entry *c;
535 constant_classref *ref;
537 DESCRIPTOR_ASSERT(pool);
539 nclasses = pool->classrefhash.entries;
540 pool->classrefs = MNEW(constant_classref,nclasses);
542 /* fill the constant_classref structs */
544 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
545 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
547 ref = pool->classrefs + c->index;
548 CLASSREF_INIT(*ref, pool->referer, c->name);
556 return pool->classrefs;
560 /* descriptor_pool_lookup_classref *********************************************
562 Return the constant_classref for the given class name
565 pool.............the descriptor_pool
566 classname........name of the class to look up
569 a pointer to the constant_classref, or
570 NULL if an exception has been thrown
572 *******************************************************************************/
575 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
578 classref_hash_entry *c;
580 DESCRIPTOR_ASSERT(pool);
581 DESCRIPTOR_ASSERT(pool->classrefs);
582 DESCRIPTOR_ASSERT(classname);
584 key = utf_hashkey(classname->text, classname->blength);
585 slot = key & (pool->classrefhash.size - 1);
586 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
589 if (c->name == classname)
590 return pool->classrefs + c->index;
595 new_exception_message(string_java_lang_InternalError,
596 "Class reference not found in descriptor pool");
601 /* descriptor_pool_alloc_parsed_descriptors ************************************
603 Allocate space for the parsed descriptors
606 pool.............the descriptor_pool
609 This function must be called after all descriptors have been added
610 with descriptor_pool_add.
612 *******************************************************************************/
615 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
619 DESCRIPTOR_ASSERT(pool);
621 /* XXX TWISTI: paramcount + 1: we don't know if the method is static or */
622 /* not, i have no better solution yet. */
625 pool->fieldcount * sizeof(typedesc) +
626 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
627 pool->paramcount * sizeof(typedesc) +
628 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
630 pool->descriptorsize = size;
632 pool->descriptors = MNEW(u1, size);
633 pool->descriptors_next = pool->descriptors;
636 size = pool->fieldcount + pool->methodcount;
638 pool->descriptor_kind = DMNEW(u1, size);
639 pool->descriptor_kind_next = pool->descriptor_kind;
644 /* descriptor_pool_parse_field_descriptor **************************************
646 Parse the given field descriptor
649 pool.............the descriptor_pool
650 desc.............the field descriptor
653 a pointer to the parsed field descriptor, or
654 NULL if an exception has been thrown
657 descriptor_pool_alloc_parsed_descriptors must be called (once)
658 before this function is used.
660 *******************************************************************************/
663 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
666 descriptor_hash_entry *d;
669 DESCRIPTOR_ASSERT(pool);
670 DESCRIPTOR_ASSERT(pool->descriptors);
671 DESCRIPTOR_ASSERT(pool->descriptors_next);
673 /* lookup the descriptor in the hashtable */
675 key = utf_hashkey(desc->text, desc->blength);
676 slot = key & (pool->descriptorhash.size - 1);
677 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
680 if (d->desc == desc) {
682 if (d->parseddesc.fd)
683 return d->parseddesc.fd;
689 DESCRIPTOR_ASSERT(d);
691 if (desc->text[0] == '(') {
692 *exceptionptr = new_classformaterror(pool->referer,
693 "Method descriptor used in field reference");
697 td = (typedesc *) pool->descriptors_next;
698 pool->descriptors_next += sizeof(typedesc);
700 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
703 *(pool->descriptor_kind_next++) = 'f';
705 d->parseddesc.fd = td;
711 /* descriptor_pool_parse_method_descriptor *************************************
713 Parse the given method descriptor
716 pool.............the descriptor_pool
717 desc.............the method descriptor
718 mflags...........the method flags
721 a pointer to the parsed method descriptor, or
722 NULL if an exception has been thrown
725 descriptor_pool_alloc_parsed_descriptors must be called
726 (once) before this function is used.
728 *******************************************************************************/
731 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
735 descriptor_hash_entry *d;
743 DESCRIPTOR_ASSERT(pool);
744 DESCRIPTOR_ASSERT(pool->descriptors);
745 DESCRIPTOR_ASSERT(pool->descriptors_next);
747 /* lookup the descriptor in the hashtable */
749 key = utf_hashkey(desc->text, desc->blength);
750 slot = key & (pool->descriptorhash.size - 1);
751 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
753 /* find an un-parsed descriptor */
757 if (!d->parseddesc.md)
762 DESCRIPTOR_ASSERT(d);
764 md = (methoddesc *) pool->descriptors_next;
765 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
767 utf_ptr = desc->text;
768 end_pos = UTF_END(desc);
770 if (*utf_ptr++ != '(') {
771 *exceptionptr = new_classformaterror(pool->referer,
772 "Field descriptor used in method reference");
778 /* count the `this' pointer */
780 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
782 td->decltype = TYPE_ADR;
787 pool->descriptors_next += sizeof(typedesc);
792 while (*utf_ptr != ')') {
793 /* parse a parameter type */
795 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
798 if (td->type == TYPE_LONG || td->type == TYPE_DOUBLE)
802 pool->descriptors_next += sizeof(typedesc);
806 utf_ptr++; /* skip ')' */
808 /* Skip possible `this' pointer in paramtypes array to allow a possible */
809 /* memory move later in parse. */
811 if (mflags == ACC_UNDEF)
812 pool->descriptors_next += sizeof(typedesc);
814 /* parse return type */
816 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
820 md->paramcount = paramcount;
821 md->paramslots = paramslots;
823 /* If m != ACC_UNDEF we parse a real loaded method, so do param prealloc. */
824 /* Otherwise we do this in stack analysis. */
826 if (mflags != ACC_UNDEF) {
827 if (md->paramcount > 0) {
828 /* allocate memory for params */
830 md->params = MNEW(paramdesc, md->paramcount);
832 /* fill the paramdesc */
838 *(pool->descriptor_kind_next++) = 'm';
840 d->parseddesc.md = md;
846 /* descriptor_params_from_paramtypes *******************************************
854 *******************************************************************************/
856 bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
860 DESCRIPTOR_ASSERT(md);
864 /* check for `this' pointer */
866 if (!(mflags & ACC_STATIC)) {
867 if (md->paramcount > 0) {
868 /* shift param types by 1 argument */
870 MMOVE(td + 1, td, typedesc, md->paramcount);
873 /* fill in first argument `this' */
876 td->decltype = TYPE_ADR;
884 /* if the method has params, process them */
886 if (md->paramcount > 0) {
887 /* allocate memory for params */
889 md->params = MNEW(paramdesc, md->paramcount);
891 /* fill the paramdesc */
900 /* descriptor_pool_get_parsed_descriptors **************************************
902 Return a pointer to the block of parsed descriptors
905 pool.............the descriptor_pool
908 *size............if size is non-NULL, this is set to the size of the
909 parsed descriptor block (in u1)
912 a pointer to the block of parsed descriptors
915 descriptor_pool_alloc_parsed_descriptors must be called (once)
916 before this function is used.
918 *******************************************************************************/
921 descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
923 DESCRIPTOR_ASSERT(pool);
924 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
927 *size = pool->descriptorsize;
929 return pool->descriptors;
933 /* descriptor_pool_get_sizes ***************************************************
935 Get the sizes of the class reference table and the parsed descriptors
938 pool.............the descriptor_pool
941 *classrefsize....set to size of the class reference table
942 *descsize........set to size of the parsed descriptors
945 This function may only be called after both
946 descriptor_pool_create_classrefs, and
947 descriptor_pool_alloc_parsed_descriptors
950 *******************************************************************************/
953 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
955 DESCRIPTOR_ASSERT(pool);
956 DESCRIPTOR_ASSERT((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
957 DESCRIPTOR_ASSERT(pool->classrefs);
958 DESCRIPTOR_ASSERT(classrefsize);
959 DESCRIPTOR_ASSERT(descsize);
961 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
962 *descsize = pool->descriptorsize;
966 /* descriptor_debug_print_typedesc *********************************************
968 Print the given typedesc to the given stream
971 file.............stream to print to
972 d................the parsed descriptor
974 *******************************************************************************/
977 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
982 fprintf(file,"(typedesc *)NULL");
986 if (d->type == TYPE_ADDRESS) {
987 utf_fprint(file,d->classref->name);
990 switch (d->decltype) {
991 case PRIMITIVETYPE_INT : ch='I'; break;
992 case PRIMITIVETYPE_CHAR : ch='C'; break;
993 case PRIMITIVETYPE_BYTE : ch='B'; break;
994 case PRIMITIVETYPE_SHORT : ch='S'; break;
995 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
996 case PRIMITIVETYPE_LONG : ch='J'; break;
997 case PRIMITIVETYPE_FLOAT : ch='F'; break;
998 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
999 case PRIMITIVETYPE_VOID : ch='V'; break;
1005 fprintf(file,"[%d]",d->arraydim);
1008 /* descriptor_debug_print_methoddesc *******************************************
1010 Print the given methoddesc to the given stream
1013 file.............stream to print to
1014 d................the parsed descriptor
1016 *******************************************************************************/
1019 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1024 fprintf(file,"(methoddesc *)NULL");
1029 for (i=0; i<d->paramcount; ++i) {
1032 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1035 descriptor_debug_print_typedesc(file,&(d->returntype));
1038 /* descriptor_pool_debug_dump **************************************************
1040 Print the state of the descriptor_pool to the given stream
1043 pool.............the descriptor_pool
1044 file.............stream to print to
1046 *******************************************************************************/
1049 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1056 fprintf(file,"======[descriptor_pool for ");
1057 utf_fprint(file,pool->referer->name);
1058 fprintf(file,"]======\n");
1060 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1061 fprintf(file,"methodcount: %d\n",pool->methodcount);
1062 fprintf(file,"paramcount: %d\n",pool->paramcount);
1063 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1064 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1065 fprintf(file,"classrefsize: %d bytes\n",
1066 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1068 fprintf(file,"class references:\n");
1069 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1070 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1072 fprintf(file," %4d: ",c->index);
1073 utf_fprint(file,c->name);
1079 fprintf(file,"hashed descriptors:\n");
1080 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1081 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1083 fprintf(file," %p: ",c->parseddesc.any);
1084 utf_fprint(file,c->desc);
1090 fprintf(file,"descriptors:\n");
1091 if (pool->descriptors) {
1092 pos = pool->descriptors;
1093 size = pool->descriptors_next - pool->descriptors;
1094 fprintf(file," size: %d bytes\n",size);
1096 if (pool->descriptor_kind) {
1097 kind = pool->descriptor_kind;
1099 while (pos < (pool->descriptors + size)) {
1100 fprintf(file," %p: ",pos);
1103 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1104 pos += sizeof(typedesc);
1107 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1108 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1109 pos += sizeof(methoddesc) - sizeof(typedesc);
1112 fprintf(file,"INVALID KIND");
1118 while (size >= sizeof(voidptr)) {
1119 fprintf(file," %p\n",*((voidptr*)pos));
1120 pos += sizeof(voidptr);
1121 size -= sizeof(voidptr);
1126 fprintf(file,"==========================================================\n");
1130 * These are local overrides for various environment variables in Emacs.
1131 * Please do not remove this and leave it at the end of the file, where
1132 * Emacs will automagically detect them.
1133 * ---------------------------------------------------------------------
1136 * indent-tabs-mode: t
1140 * vim:noexpandtab:sw=4:ts=4: