1 /* src/vm/descriptor.c - checking and parsing of field / method descriptors
3 Copyright (C) 1996-2011
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "mm/memory.hpp"
36 #include "vm/descriptor.hpp"
37 #include "vm/exceptions.hpp"
38 #include "vm/options.h"
39 #include "vm/primitive.hpp"
42 #include "vm/jit/abi.h"
45 /* constants (private to descriptor.c) ****************************************/
47 /* initial number of entries for the classrefhash of a descriptor_pool */
48 /* (currently the hash is never grown!) */
49 #define CLASSREFHASH_INIT_SIZE 64
51 /* initial number of entries for the descriptorhash of a descriptor_pool */
52 /* (currently the hash is never grown!) */
53 #define DESCRIPTORHASH_INIT_SIZE 128
55 /* data structures (private to descriptor.c) **********************************/
57 typedef struct classref_hash_entry classref_hash_entry;
58 typedef struct descriptor_hash_entry descriptor_hash_entry;
60 /* entry struct for the classrefhash of descriptor_pool */
61 struct classref_hash_entry {
62 classref_hash_entry *hashlink; /* for hash chaining */
63 utf *name; /* name of the class refered to */
64 u2 index; /* index into classref table */
67 /* entry struct for the descriptorhash of descriptor_pool */
68 struct descriptor_hash_entry {
69 descriptor_hash_entry *hashlink;
71 parseddesc_t parseddesc;
72 s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
76 /****************************************************************************/
77 /* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
78 /****************************************************************************/
80 /* SKIP_FIELDDESCRIPTOR:
81 * utf_ptr must point to the first character of a field descriptor.
82 * After the macro call utf_ptr points to the first character after
83 * the field descriptor.
85 * CAUTION: This macro does not check for an unexpected end of the
86 * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
88 #define SKIP_FIELDDESCRIPTOR(utf_ptr) \
89 do { while (*(utf_ptr)=='[') (utf_ptr)++; \
90 if (*(utf_ptr)++=='L') \
91 while(*(utf_ptr)++ != ';') /* skip */; } while(0)
93 /* SKIP_FIELDDESCRIPTOR_SAFE:
94 * utf_ptr must point to the first character of a field descriptor.
95 * After the macro call utf_ptr points to the first character after
96 * the field descriptor.
99 * utf_ptr....points to first char of descriptor
100 * end_ptr....points to first char after the end of the string
101 * errorflag..must be initialized (to false) by the caller!
103 * utf_ptr....points to first char after the descriptor
104 * errorflag..set to true if the string ended unexpectedly
106 #define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
107 do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
108 if ((utf_ptr) == (end_ptr)) \
109 (errorflag) = true; \
111 if (*(utf_ptr)++=='L') { \
112 while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
114 if ((utf_ptr)[-1] != ';') \
115 (errorflag) = true; }} while(0)
118 #if defined(__cplusplus)
122 /****************************************************************************/
124 /****************************************************************************/
126 /*#define DESCRIPTOR_VERBOSE*/
128 /****************************************************************************/
130 /****************************************************************************/
132 /* descriptor_to_basic_type ****************************************************
134 Return the basic type to use for a value with this descriptor.
137 utf..............descriptor utf string
143 This function assumes that the descriptor has passed
144 descriptor_pool_add checks and that it does not start with '('.
146 *******************************************************************************/
148 int descriptor_to_basic_type(utf *descriptor)
150 assert(descriptor->blength >= 1);
152 switch (descriptor->text[0]) {
174 vm_abort("descriptor_to_basic_type: invalid type %c",
175 descriptor->text[0]);
178 /* keep the compiler happy */
184 /* descriptor_typesize *********************************************************
186 Return the size in bytes needed for the given type.
189 td..............typedesc describing the type
194 *******************************************************************************/
196 int descriptor_typesize(typedesc *td)
210 return SIZEOF_VOID_P;
213 vm_abort("descriptor_typesize: invalid type %d", td->type);
216 /* keep the compiler happy */
222 /* name_from_descriptor ********************************************************
224 Return the class name indicated by the given descriptor
225 (Internally used helper function)
228 c................class containing the descriptor
229 utf_ptr..........first character of descriptor
230 end_ptr..........first character after the end of the string
231 mode.............a combination (binary or) of the following flags:
233 (Flags marked with * are the default settings.)
235 How to handle "V" descriptors:
237 * DESCRIPTOR_VOID.....handle it like other primitive types
238 DESCRIPTOR_NOVOID...treat it as an error
240 How to deal with extra characters after the end of the
243 * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
244 DESCRIPTOR_CHECKEND.....treat them as an error
247 *next............if non-NULL, *next is set to the first character after
248 the descriptor. (Undefined if an error occurs.)
249 *name............set to the utf name of the class
252 true.............descriptor parsed successfully
253 false............an exception has been thrown
255 *******************************************************************************/
257 #define DESCRIPTOR_VOID 0 /* default */
258 #define DESCRIPTOR_NOVOID 0x0040
259 #define DESCRIPTOR_NOCHECKEND 0 /* default */
260 #define DESCRIPTOR_CHECKEND 0x1000
263 name_from_descriptor(classinfo *c,
264 char *utf_ptr, char *end_ptr,
265 char **next, int mode, utf **name)
267 char *start = utf_ptr;
276 SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
278 if (mode & DESCRIPTOR_CHECKEND)
279 error |= (utf_ptr != end_ptr);
282 if (next) *next = utf_ptr;
286 if (mode & DESCRIPTOR_NOVOID)
304 *name = utf_new(start, utf_ptr - start);
309 exceptions_throw_classformaterror(c, "Invalid descriptor");
314 /* descriptor_to_typedesc ******************************************************
316 Parse the given type descriptor and fill a typedesc struct
317 (Internally used helper function)
320 pool.............the descriptor pool
321 utf_ptr..........points to first character of type descriptor
322 end_pos..........points after last character of the whole descriptor
325 *next............set to next character after type descriptor
326 *d...............filled with parsed information
329 true.............parsing succeeded
330 false............an exception has been thrown
332 *******************************************************************************/
335 descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
336 char **next, typedesc *td)
340 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
344 /* a reference type */
346 td->primitivetype = TYPE_ADR;
348 for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
350 td->classref = descriptor_pool_lookup_classref(pool, name);
353 /* a primitive type */
356 td->primitivetype = PRIMITIVETYPE_BYTE;
360 td->primitivetype = PRIMITIVETYPE_CHAR;
364 td->primitivetype = PRIMITIVETYPE_SHORT;
368 td->primitivetype = PRIMITIVETYPE_BOOLEAN;
372 td->primitivetype = PRIMITIVETYPE_INT;
376 td->primitivetype = PRIMITIVETYPE_DOUBLE;
380 td->primitivetype = PRIMITIVETYPE_FLOAT;
384 td->primitivetype = PRIMITIVETYPE_LONG;
388 td->primitivetype = PRIMITIVETYPE_VOID;
389 td->type = TYPE_VOID;
403 /* descriptor_pool_new *********************************************************
405 Allocate a new descriptor_pool
408 referer..........class for which to create the pool
411 a pointer to the new descriptor_pool
413 *******************************************************************************/
416 descriptor_pool_new(classinfo *referer)
418 descriptor_pool *pool;
422 pool = (descriptor_pool*) DumpMemory::allocate(sizeof(descriptor_pool));
425 pool->referer = referer;
426 pool->fieldcount = 0;
427 pool->methodcount = 0;
428 pool->paramcount = 0;
429 pool->descriptorsize = 0;
430 pool->descriptors = NULL;
431 pool->descriptors_next = NULL;
432 pool->classrefs = NULL;
433 pool->descriptor_kind = NULL;
434 pool->descriptor_kind_next = NULL;
436 hashsize = CLASSREFHASH_INIT_SIZE;
437 pool->classrefhash.size = hashsize;
438 pool->classrefhash.entries = 0;
439 pool->classrefhash.ptr = (void **) DumpMemory::allocate(sizeof(void*) * hashsize);
440 for (slot=0; slot<hashsize; ++slot)
441 pool->classrefhash.ptr[slot] = NULL;
443 hashsize = DESCRIPTORHASH_INIT_SIZE;
444 pool->descriptorhash.size = hashsize;
445 pool->descriptorhash.entries = 0;
446 pool->descriptorhash.ptr = (void**) DumpMemory::allocate(sizeof(void*) * hashsize);
447 for (slot=0; slot<hashsize; ++slot)
448 pool->descriptorhash.ptr[slot] = NULL;
454 /* descriptor_pool_add_class ***************************************************
456 Add the given class reference to the pool
459 pool.............the descriptor_pool
460 name.............the class reference to add
463 true.............reference has been added
464 false............an exception has been thrown
466 *******************************************************************************/
469 descriptor_pool_add_class(descriptor_pool *pool, utf *name)
472 classref_hash_entry *c;
477 #ifdef DESCRIPTOR_VERBOSE
478 fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
479 utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
482 /* find a place in the hashtable */
484 key = utf_hashkey(name->text, name->blength);
485 slot = key & (pool->classrefhash.size - 1);
486 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
490 return true; /* already stored */
494 /* check if the name is a valid classname */
496 if (!is_valid_name(name->text,UTF_END(name))) {
497 exceptions_throw_classformaterror(pool->referer, "Invalid class name");
498 return false; /* exception */
501 /* XXX check maximum array dimension */
503 c = (classref_hash_entry*) DumpMemory::allocate(sizeof(classref_hash_entry));
505 c->index = pool->classrefhash.entries++;
506 c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
507 pool->classrefhash.ptr[slot] = c;
513 /* descriptor_pool_add *********************************************************
515 Check the given descriptor and add it to the pool
518 pool.............the descriptor_pool
519 desc.............the descriptor to add. Maybe a field or method desc.
522 *paramslots......if non-NULL, set to the number of parameters.
523 LONG and DOUBLE are counted twice
526 true.............descriptor has been added
527 false............an exception has been thrown
529 *******************************************************************************/
532 descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
535 descriptor_hash_entry *d;
541 #ifdef DESCRIPTOR_VERBOSE
542 fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
543 utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
549 /* find a place in the hashtable */
551 key = utf_hashkey(desc->text, desc->blength);
552 slot = key & (pool->descriptorhash.size - 1);
553 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
555 /* Save all method descriptors in the hashtable, since the parsed */
556 /* descriptor may vary between differenf methods (static vs. non-static). */
558 utf_ptr = desc->text;
560 if (*utf_ptr != '(') {
562 if (d->desc == desc) {
564 *paramslots = d->paramslots;
565 return true; /* already stored */
571 /* add the descriptor to the pool */
573 d = (descriptor_hash_entry*) DumpMemory::allocate(sizeof(descriptor_hash_entry));
575 d->parseddesc.any = NULL;
576 d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
577 pool->descriptorhash.ptr[slot] = d;
579 /* now check the descriptor */
581 end_pos = UTF_END(desc);
583 if (*utf_ptr == '(') {
584 /* a method descriptor */
589 /* check arguments */
591 while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
594 /* We cannot count the `this' argument here because
595 * we don't know if the method is static. */
597 if (*utf_ptr == 'J' || *utf_ptr == 'D')
602 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
603 DESCRIPTOR_NOVOID, &name))
607 if (!descriptor_pool_add_class(pool, name))
611 if (utf_ptr == end_pos) {
612 exceptions_throw_classformaterror(pool->referer,
613 "Missing ')' in method descriptor");
617 utf_ptr++; /* skip ')' */
619 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
620 DESCRIPTOR_CHECKEND, &name))
624 if (!descriptor_pool_add_class(pool,name))
627 if (argcount > 255) {
628 exceptions_throw_classformaterror(pool->referer,
629 "Too many arguments in signature");
634 /* a field descriptor */
638 if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
639 DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
644 if (!descriptor_pool_add_class(pool,name))
648 d->paramslots = argcount;
651 *paramslots = argcount;
657 /* descriptor_pool_create_classrefs ********************************************
659 Create a table containing all the classrefs which were added to the pool
662 pool.............the descriptor_pool
665 *count...........if count is non-NULL, this is set to the number
666 of classrefs in the table
669 a pointer to the constant_classref table
671 *******************************************************************************/
674 descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
678 classref_hash_entry *c;
679 constant_classref *ref;
683 nclasses = pool->classrefhash.entries;
684 pool->classrefs = MNEW(constant_classref,nclasses);
686 /* fill the constant_classref structs */
688 for (slot = 0; slot < pool->classrefhash.size; ++slot) {
689 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
691 ref = pool->classrefs + c->index;
692 CLASSREF_INIT(*ref, pool->referer, c->name);
700 return pool->classrefs;
704 /* descriptor_pool_lookup_classref *********************************************
706 Return the constant_classref for the given class name
709 pool.............the descriptor_pool
710 classname........name of the class to look up
713 a pointer to the constant_classref, or
714 NULL if an exception has been thrown
716 *******************************************************************************/
719 descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
722 classref_hash_entry *c;
725 assert(pool->classrefs);
728 key = utf_hashkey(classname->text, classname->blength);
729 slot = key & (pool->classrefhash.size - 1);
730 c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
733 if (c->name == classname)
734 return pool->classrefs + c->index;
738 exceptions_throw_internalerror("Class reference not found in descriptor pool");
743 /* descriptor_pool_alloc_parsed_descriptors ************************************
745 Allocate space for the parsed descriptors
748 pool.............the descriptor_pool
751 This function must be called after all descriptors have been added
752 with descriptor_pool_add.
754 *******************************************************************************/
757 descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
763 /* TWISTI: paramcount + 1: we don't know if the method is static or */
764 /* not, i have no better solution yet. */
767 pool->fieldcount * sizeof(typedesc) +
768 pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
769 pool->paramcount * sizeof(typedesc) +
770 pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
772 pool->descriptorsize = size;
774 size += sizeof(Mutex); /* prepend Mutex */
775 pool->descriptors = MNEW(u1, size);
776 /* call Mutex constructor */
777 new (reinterpret_cast<Mutex*>(pool->descriptors)) Mutex;
778 pool->descriptors += sizeof(Mutex);
779 pool->descriptors_next = pool->descriptors;
782 size = pool->fieldcount + pool->methodcount;
784 pool->descriptor_kind = (u1*) DumpMemory::allocate(sizeof(u1) * size);
785 pool->descriptor_kind_next = pool->descriptor_kind;
790 /* descriptor_pool_parse_field_descriptor **************************************
792 Parse the given field descriptor
795 pool.............the descriptor_pool
796 desc.............the field descriptor
799 a pointer to the parsed field descriptor, or
800 NULL if an exception has been thrown
803 descriptor_pool_alloc_parsed_descriptors must be called (once)
804 before this function is used.
806 *******************************************************************************/
809 descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
812 descriptor_hash_entry *d;
816 assert(pool->descriptors);
817 assert(pool->descriptors_next);
819 /* lookup the descriptor in the hashtable */
821 key = utf_hashkey(desc->text, desc->blength);
822 slot = key & (pool->descriptorhash.size - 1);
823 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
826 if (d->desc == desc) {
828 if (d->parseddesc.fd)
829 return d->parseddesc.fd;
837 if (desc->text[0] == '(') {
838 exceptions_throw_classformaterror(pool->referer,
839 "Method descriptor used in field reference");
843 td = (typedesc *) pool->descriptors_next;
844 pool->descriptors_next += sizeof(typedesc);
846 if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
849 *(pool->descriptor_kind_next++) = 'f';
851 d->parseddesc.fd = td;
857 /* descriptor_pool_parse_method_descriptor *************************************
859 Parse the given method descriptor
862 pool.............the descriptor_pool
863 desc.............the method descriptor
864 mflags...........the method flags
865 thisclass........classref to the class containing the method.
866 This is ignored if mflags contains ACC_STATIC.
867 The classref is stored for inserting the 'this' argument.
870 a pointer to the parsed method descriptor, or
871 NULL if an exception has been thrown
874 descriptor_pool_alloc_parsed_descriptors must be called
875 (once) before this function is used.
877 *******************************************************************************/
880 descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
881 s4 mflags,constant_classref *thisclass)
884 descriptor_hash_entry *d;
892 #ifdef DESCRIPTOR_VERBOSE
893 fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
894 (void*)pool,(int)mflags,(void*)thisclass);
895 utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
899 assert(pool->descriptors);
900 assert(pool->descriptors_next);
902 /* check that it is a method descriptor */
904 if (desc->text[0] != '(') {
905 exceptions_throw_classformaterror(pool->referer,
906 "Field descriptor used in method reference");
910 /* lookup the descriptor in the hashtable */
912 key = utf_hashkey(desc->text, desc->blength);
913 slot = key & (pool->descriptorhash.size - 1);
914 d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
916 /* find an un-parsed descriptor */
920 if (!d->parseddesc.md)
927 md = (methoddesc *) pool->descriptors_next;
928 md->pool_lock = reinterpret_cast<Mutex*>(pool->descriptors - sizeof(Mutex));
929 pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
931 utf_ptr = desc->text + 1; /* skip '(' */
932 end_pos = UTF_END(desc);
936 /* count the `this' pointer */
938 if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
940 td->primitivetype = TYPE_ADR;
942 td->classref = thisclass;
945 pool->descriptors_next += sizeof(typedesc);
950 while (*utf_ptr != ')') {
951 /* parse a parameter type */
953 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
956 if (IS_2_WORD_TYPE(td->type))
960 pool->descriptors_next += sizeof(typedesc);
964 utf_ptr++; /* skip ')' */
966 /* Skip possible `this' pointer in paramtypes array to allow a possible */
967 /* memory move later in parse. */
968 /* We store the thisclass reference, so we can later correctly fill in */
969 /* the parameter slot of the 'this' argument. */
971 if (mflags == ACC_UNDEF) {
972 td->classref = thisclass;
974 pool->descriptors_next += sizeof(typedesc);
977 /* parse return type */
979 if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
983 md->paramcount = paramcount;
984 md->paramslots = paramslots;
986 /* If mflags != ACC_UNDEF we parse a real loaded method, so do
987 param prealloc. Otherwise we do this in stack analysis. */
989 if (mflags != ACC_UNDEF) {
990 if (md->paramcount > 0) {
991 /* allocate memory for params */
993 md->params = MNEW(paramdesc, md->paramcount);
996 md->params = METHODDESC_NOPARAMS;
999 /* fill the paramdesc */
1000 /* md_param_alloc has to be called if md->paramcount == 0,
1001 too, so it can make the reservation for the Linkage Area,
1002 Return Register... */
1004 #if defined(ENABLE_JIT)
1005 # if defined(ENABLE_INTRP)
1009 /* As builtin-functions are native functions, we have
1010 to pre-allocate for the native ABI. */
1012 if (mflags & ACC_METHOD_BUILTIN)
1013 md_param_alloc_native(md);
1019 /* params already initialized; no need to lock */
1020 md->pool_lock = NULL;
1023 /* params will be allocated later by
1024 descriptor_params_from_paramtypes if necessary */
1029 *(pool->descriptor_kind_next++) = 'm';
1031 d->parseddesc.md = md;
1036 /* descriptor_params_from_paramtypes *******************************************
1038 Create the paramdescs for a method descriptor. This function is
1039 called when we know whether the method is static or not. This
1040 function does nothing if md->params != NULL (checked atomically).
1043 md...............the parsed method descriptor
1044 mflags...........the ACC_* access flags of the method. Only the
1045 ACC_STATIC bit is checked.
1046 The value ACC_UNDEF is NOT allowed.
1051 *******************************************************************************/
1053 void descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
1055 bool has_lock = md->pool_lock;
1059 md->pool_lock->lock();
1062 md->pool_lock->unlock();
1065 assert(md->params == NULL);
1066 assert(mflags != ACC_UNDEF);
1068 typedesc *td = md->paramtypes;
1070 /* check for `this' pointer */
1072 if (!(mflags & ACC_STATIC)) {
1073 constant_classref *thisclass;
1075 /* fetch class reference from reserved param slot */
1076 thisclass = td[md->paramcount].classref;
1079 if (md->paramcount > 0) {
1080 /* shift param types by 1 argument */
1081 MMOVE(td + 1, td, typedesc, md->paramcount);
1084 /* fill in first argument `this' */
1086 td->type = TYPE_ADR;
1087 td->primitivetype = TYPE_ADR;
1089 td->classref = thisclass;
1095 /* if the method has params, process them */
1097 if (md->paramcount > 0) {
1098 /* allocate memory for params */
1100 md->params = MNEW(paramdesc, md->paramcount);
1103 md->params = METHODDESC_NOPARAMS;
1106 /* fill the paramdesc */
1107 /* md_param_alloc has to be called if md->paramcount == 0, too, so
1108 it can make the reservation for the Linkage Area, Return
1111 #if defined(ENABLE_JIT)
1112 # if defined(ENABLE_INTRP)
1116 /* As builtin-functions are native functions, we have to
1117 pre-allocate for the native ABI. */
1119 if (mflags & ACC_METHOD_BUILTIN)
1120 md_param_alloc_native(md);
1127 md->pool_lock->unlock();
1131 /* descriptor_pool_get_sizes ***************************************************
1133 Get the sizes of the class reference table and the parsed descriptors
1136 pool.............the descriptor_pool
1139 *classrefsize....set to size of the class reference table
1140 *descsize........set to size of the parsed descriptors
1143 This function may only be called after both
1144 descriptor_pool_create_classrefs, and
1145 descriptor_pool_alloc_parsed_descriptors
1148 *******************************************************************************/
1151 descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
1154 assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
1155 assert(pool->classrefs);
1156 assert(classrefsize);
1159 *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
1160 *descsize = pool->descriptorsize;
1164 /****************************************************************************/
1166 /****************************************************************************/
1169 /* descriptor_debug_print_typedesc *********************************************
1171 Print the given typedesc to the given stream
1174 file.............stream to print to
1175 d................the parsed descriptor
1177 *******************************************************************************/
1180 descriptor_debug_print_typedesc(FILE *file,typedesc *d)
1185 fprintf(file,"(typedesc *)NULL");
1189 if (d->type == TYPE_ADR) {
1191 utf_fprint_printable_ascii(file,d->classref->name);
1193 fprintf(file,"<class=NULL>");
1196 switch (d->primitivetype) {
1197 case PRIMITIVETYPE_INT : ch='I'; break;
1198 case PRIMITIVETYPE_CHAR : ch='C'; break;
1199 case PRIMITIVETYPE_BYTE : ch='B'; break;
1200 case PRIMITIVETYPE_SHORT : ch='S'; break;
1201 case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
1202 case PRIMITIVETYPE_LONG : ch='J'; break;
1203 case PRIMITIVETYPE_FLOAT : ch='F'; break;
1204 case PRIMITIVETYPE_DOUBLE : ch='D'; break;
1205 case PRIMITIVETYPE_VOID : ch='V'; break;
1211 fprintf(file,"[%d]",d->arraydim);
1214 /* descriptor_debug_print_paramdesc ********************************************
1216 Print the given paramdesc to the given stream
1219 file.............stream to print to
1220 d................the parameter descriptor
1222 *******************************************************************************/
1225 descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
1228 fprintf(file,"(paramdesc *)NULL");
1233 fprintf(file,"<m%d>",d->regoff);
1236 fprintf(file,"<r%d>",d->regoff);
1240 /* descriptor_debug_print_methoddesc *******************************************
1242 Print the given methoddesc to the given stream
1245 file.............stream to print to
1246 d................the parsed descriptor
1248 *******************************************************************************/
1251 descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
1256 fprintf(file,"(methoddesc *)NULL");
1261 for (i=0; i<d->paramcount; ++i) {
1264 descriptor_debug_print_typedesc(file,d->paramtypes + i);
1266 descriptor_debug_print_paramdesc(file,d->params + i);
1269 if (d->params == METHODDESC_NOPARAMS)
1270 fputs("<NOPARAMS>",file);
1272 descriptor_debug_print_typedesc(file,&(d->returntype));
1275 /* descriptor_pool_debug_dump **************************************************
1277 Print the state of the descriptor_pool to the given stream
1280 pool.............the descriptor_pool
1281 file.............stream to print to
1283 *******************************************************************************/
1286 descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
1293 fprintf(file,"======[descriptor_pool for ");
1294 utf_fprint_printable_ascii(file,pool->referer->name);
1295 fprintf(file,"]======\n");
1297 fprintf(file,"fieldcount: %d\n",pool->fieldcount);
1298 fprintf(file,"methodcount: %d\n",pool->methodcount);
1299 fprintf(file,"paramcount: %d\n",pool->paramcount);
1300 fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
1301 fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
1302 fprintf(file,"classrefsize: %d bytes\n",
1303 (int)(pool->classrefhash.entries * sizeof(constant_classref)));
1305 fprintf(file,"class references:\n");
1306 for (slot=0; slot<pool->classrefhash.size; ++slot) {
1307 classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
1309 fprintf(file," %4d: ",c->index);
1310 utf_fprint_printable_ascii(file,c->name);
1316 fprintf(file,"hashed descriptors:\n");
1317 for (slot=0; slot<pool->descriptorhash.size; ++slot) {
1318 descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
1320 fprintf(file," %p: ",c->parseddesc.any);
1321 utf_fprint_printable_ascii(file,c->desc);
1327 fprintf(file,"descriptors:\n");
1328 if (pool->descriptors) {
1329 pos = pool->descriptors;
1330 size = pool->descriptors_next - pool->descriptors;
1331 fprintf(file," size: %d bytes\n",size);
1333 if (pool->descriptor_kind) {
1334 kind = pool->descriptor_kind;
1336 while (pos < (pool->descriptors + size)) {
1337 fprintf(file," %p: ",pos);
1340 descriptor_debug_print_typedesc(file,(typedesc*)pos);
1341 pos += sizeof(typedesc);
1344 descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
1345 pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
1346 pos += sizeof(methoddesc) - sizeof(typedesc);
1349 fprintf(file,"INVALID KIND");
1355 while (size >= sizeof(void*)) {
1356 fprintf(file," %p\n",*((void**)pos));
1357 pos += sizeof(void*);
1358 size -= sizeof(void*);
1363 fprintf(file,"==========================================================\n");
1365 #endif /* !defined(NDEBUG) */
1367 #if defined(__cplusplus)
1372 * These are local overrides for various environment variables in Emacs.
1373 * Please do not remove this and leave it at the end of the file, where
1374 * Emacs will automagically detect them.
1375 * ---------------------------------------------------------------------
1378 * indent-tabs-mode: t
1382 * vim:noexpandtab:sw=4:ts=4: