1 /* src/vm/resolve.c - resolving classes/interfaces/fields/methods
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
31 $Id: resolve.c 2102 2005-03-28 22:09:35Z twisti $
37 #include "vm/resolve.h"
38 #include "vm/access.h"
39 #include "vm/classcache.h"
40 #include "vm/exceptions.h"
41 #include "vm/linker.h"
42 #include "vm/classcache.h"
43 #include "vm/descriptor.h"
44 #include "vm/jit/jit.h"
45 #include "vm/jit/verify/typeinfo.h"
47 /******************************************************************************/
49 /******************************************************************************/
56 #define RESOLVE_ASSERT(cond) assert(cond)
58 #define RESOLVE_ASSERT(cond)
61 /******************************************************************************/
62 /* CLASS RESOLUTION */
63 /******************************************************************************/
65 /* resolve symbolic class reference -- see resolve.h */
67 resolve_class(classinfo *referer,methodinfo *refmethod,
72 classinfo *cls = NULL;
74 RESOLVE_ASSERT(result);
75 RESOLVE_ASSERT(referer);
76 RESOLVE_ASSERT(classname);
77 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
82 fprintf(stderr,"resolve_class(");
83 utf_fprint(stderr,referer->name);
85 utf_fprint(stderr,classname);
86 fprintf(stderr,")\n");
89 /* lookup if this class has already been loaded */
90 cls = classcache_lookup(referer->classloader,classname);
93 fprintf(stderr," lookup result: %p\n",(void*)cls);
97 /* the class has not been loaded, yet */
98 if (mode == resolveLazy)
99 return true; /* be lazy */
102 fprintf(stderr," loading...\n");
107 if (!load_class(referer->classloader,classname,&cls))
108 return false; /* exception */
110 cls = class_new(classname);
116 /* the class is now loaded */
118 RESOLVE_ASSERT(cls->loaded);
121 fprintf(stderr," checking access rights...\n");
124 /* check access rights of referer to refered class */
125 if (!is_accessible_class(referer,cls)) {
126 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
127 "class is not accessible XXX add message");
128 return false; /* exception */
131 /* resolution succeeds */
133 fprintf(stderr," success.\n");
140 resolve_classref_or_classinfo(methodinfo *refmethod,
141 classref_or_classinfo cls,
148 RESOLVE_ASSERT(cls.any);
149 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
150 RESOLVE_ASSERT(result);
154 if (IS_CLASSREF(cls)) {
155 /* we must resolve this reference */
156 if (!resolve_class(cls.ref->referer,refmethod,cls.ref->name,
158 return false; /* exception */
161 /* cls has already been resolved */
165 return false; /* exception */
167 RESOLVE_ASSERT(c || (mode == resolveLazy));
170 return true; /* be lazy */
173 RESOLVE_ASSERT(c->loaded);
178 return false; /* exception */
179 RESOLVE_ASSERT(c->linked);
187 /******************************************************************************/
188 /* SUBTYPE SET CHECKS */
189 /******************************************************************************/
191 /* for documentation see resolve.h */
193 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
194 unresolved_subtype_set *ref,
195 classref_or_classinfo typeref,
201 classref_or_classinfo *setp;
207 RESOLVE_ASSERT(referer);
209 RESOLVE_ASSERT(typeref.any);
210 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
211 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
214 fprintf(stderr,"resolve_and_check_subtype_set\n");
215 unresolved_subtype_set_debug_dump(ref,stderr);
216 if (IS_CLASSREF(typeref)) {
217 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
220 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
222 fprintf(stderr,"\n");
225 setp = ref->subtyperefs;
227 /* an empty set of tests always succeeds */
228 if (!setp || !setp->any) {
237 /* first resolve the type if necessary */
238 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
239 return false; /* exception */
241 return true; /* be lazy */
243 RESOLVE_ASSERT(type);
244 RESOLVE_ASSERT(type->loaded);
245 RESOLVE_ASSERT(type->linked);
246 TYPEINFO_INIT_CLASSINFO(typeti,type);
248 for (; setp->any; ++setp) {
249 /* first resolve the set member if necessary */
250 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
251 return false; /* exception */
253 return true; /* be lazy */
255 RESOLVE_ASSERT(result);
256 RESOLVE_ASSERT(result->loaded);
257 RESOLVE_ASSERT(result->linked);
260 fprintf(stderr,"performing subclass test:\n");
261 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
262 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
263 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
266 /* now check the subtype relationship */
267 TYPEINFO_INIT_CLASSINFO(resultti,result);
269 if (!typeinfo_is_assignable_to_classinfo(&typeti,result)) {
271 fprintf(stderr,"reversed subclass test failed\n");
277 if (!typeinfo_is_assignable_to_classinfo(&resultti,type)) {
279 fprintf(stderr,"subclass test failed\n");
292 if (error == resolveIllegalAccessError)
293 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
294 "illegal access to protected member XXX add message");
296 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
297 "subtype constraint violated XXX add message");
298 return false; /* exception */
301 /******************************************************************************/
302 /* FIELD RESOLUTION */
303 /******************************************************************************/
305 /* for documentation see resolve.h */
307 resolve_field(unresolved_field *ref,
312 classinfo *container;
314 constant_classref *fieldtyperef;
319 RESOLVE_ASSERT(result);
320 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
325 unresolved_field_debug_dump(ref,stderr);
328 /* the class containing the reference */
329 referer = ref->fieldref->classref->referer;
330 RESOLVE_ASSERT(referer);
332 /* first we must resolve the class containg the field */
333 if (!resolve_class(referer,ref->referermethod,
334 ref->fieldref->classref->name,mode,&container))
336 /* the class reference could not be resolved */
337 return false; /* exception */
340 return true; /* be lazy */
342 RESOLVE_ASSERT(container);
343 RESOLVE_ASSERT(container->loaded && container->linked);
345 /* now we must find the declaration of the field in `container`
346 * or one of its superclasses */
349 fprintf(stderr," resolving field in class...\n");
352 fi = class_resolvefield(container,
353 ref->fieldref->name,ref->fieldref->descriptor,
356 return false; /* exception */
358 /* { the field reference has been resolved } */
359 declarer = fi->class;
360 RESOLVE_ASSERT(declarer);
361 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
364 fprintf(stderr," checking static...\n");
368 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
369 /* a static field is accessed via an instance, or vice versa */
370 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
371 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
372 : "instance field accessed without instance");
373 return false; /* exception */
376 /* for non-static accesses we have to check the constraints on the instance type */
377 if ((ref->flags & RESOLVE_STATIC) == 0) {
379 fprintf(stderr," checking instance types...\n");
382 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
383 &(ref->instancetypes),
384 CLASSREF_OR_CLASSINFO(container),
387 resolveLinkageError,&checked))
389 return false; /* exception */
392 return true; /* be lazy */
395 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
397 /* for PUT* instructions we have to check the constraints on the value type */
398 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
399 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
400 /* check subtype constraints */
401 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
402 &(ref->valueconstraints),
403 CLASSREF_OR_CLASSINFO(fieldtyperef),
406 resolveLinkageError,&checked))
408 return false; /* exception */
411 return true; /* be lazy */
415 /* check access rights */
416 if (!is_accessible_member(referer,declarer,fi->flags)) {
417 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
418 "field is not accessible XXX add message");
419 return false; /* exception */
422 /* check protected access */
423 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
424 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
425 &(ref->instancetypes),
426 CLASSREF_OR_CLASSINFO(referer),
429 resolveIllegalAccessError,&checked))
431 return false; /* exception */
434 return true; /* be lazy */
437 /* impose loading constraint on field type */
438 if (fi->type == TYPE_ADR) {
439 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
441 return false; /* exception */
449 /******************************************************************************/
450 /* METHOD RESOLUTION */
451 /******************************************************************************/
453 /* for documentation see resolve.h */
455 resolve_method(unresolved_method *ref,
460 classinfo *container;
463 typedesc *paramtypes;
469 RESOLVE_ASSERT(result);
470 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
473 unresolved_method_debug_dump(ref,stderr);
478 /* the class containing the reference */
479 referer = ref->methodref->classref->referer;
480 RESOLVE_ASSERT(referer);
482 /* first we must resolve the class containg the method */
483 if (!resolve_class(referer,ref->referermethod,
484 ref->methodref->classref->name,mode,&container))
486 /* the class reference could not be resolved */
487 return false; /* exception */
490 return true; /* be lazy */
492 RESOLVE_ASSERT(container);
494 /* now we must find the declaration of the method in `container`
495 * or one of its superclasses */
497 if ((container->flags & ACC_INTERFACE) != 0) {
498 mi = class_resolveinterfacemethod(container,
499 ref->methodref->name,ref->methodref->descriptor,
503 mi = class_resolveclassmethod(container,
504 ref->methodref->name,ref->methodref->descriptor,
508 return false; /* exception */ /* XXX set exceptionptr? */
510 /* { the method reference has been resolved } */
511 declarer = mi->class;
512 RESOLVE_ASSERT(declarer);
515 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
516 /* a static method is accessed via an instance, or vice versa */
517 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
518 (mi->flags & ACC_STATIC) ? "static method called via instance"
519 : "instance method called without instance");
520 return false; /* exception */
523 /* for non-static methods we have to check the constraints on the instance type */
524 if ((ref->flags & RESOLVE_STATIC) == 0) {
525 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
526 &(ref->instancetypes),
527 CLASSREF_OR_CLASSINFO(container),
530 resolveLinkageError,&checked))
532 return false; /* exception */
535 return true; /* be lazy */
542 /* check subtype constraints for TYPE_ADR parameters */
543 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
544 paramtypes = ref->methodref->parseddesc.md->paramtypes;
546 for (i=0; i<(mi->paramcount-instancecount); ++i) {
547 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
548 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
549 if (ref->paramconstraints) {
550 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
551 ref->paramconstraints + i,
552 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
555 resolveLinkageError,&checked))
557 return false; /* exception */
560 return true; /* be lazy */
565 /* check access rights */
566 if (!is_accessible_member(referer,declarer,mi->flags)) {
567 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
568 "method is not accessible XXX add message");
569 return false; /* exception */
572 /* check protected access */
573 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
574 /* XXX do we also need to check (referer subclass_of declarer)? */
575 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
576 &(ref->instancetypes),
577 CLASSREF_OR_CLASSINFO(referer),
580 resolveIllegalAccessError,&checked))
582 return false; /* exception */
585 return true; /* be lazy */
588 /* impose loading constraints on parameters (including instance) */
589 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
590 for (i=0; i<mi->paramcount; ++i) {
591 if (mi->paramtypes[i] == TYPE_ADR) {
594 if (i < instancecount)
595 name = container->name; /* XXX should this be declarer->name? */
597 name = paramtypes[i].classref->name;
599 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
600 return false; /* exception */
604 /* impose loading constraing onto return type */
605 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
606 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
607 ref->methodref->parseddesc.md->returntype.classref->name))
608 return false; /* exception */
616 /******************************************************************************/
617 /* CREATING THE DATA STRUCTURES */
618 /******************************************************************************/
621 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
622 unresolved_subtype_set *stset,typeinfo *tinfo,
623 constant_classref *declaredtype)
628 RESOLVE_ASSERT(stset);
629 RESOLVE_ASSERT(tinfo);
632 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
633 #ifdef TYPEINFO_DEBUG
634 typeinfo_print(stderr,tinfo,4);
635 fprintf(stderr,"\n");
637 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
638 fprintf(stderr,"\n");
641 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
642 *exceptionptr = new_verifyerror(refmethod,
643 "Invalid use of returnAddress");
647 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
648 *exceptionptr = new_verifyerror(refmethod,
649 "Invalid use of uninitialized object");
653 /* the nulltype is always assignable (XXX for reversed?) */
654 if (TYPEINFO_IS_NULLTYPE(*tinfo))
657 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
658 if (declaredtype->name == utf_java_lang_Object
659 && referer->classloader == NULL)
665 count = tinfo->merged->count;
666 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
667 for (i=0; i<count; ++i) {
668 stset->subtyperefs[i].cls = tinfo->merged->list[i];
670 stset->subtyperefs[count].any = NULL; /* terminate */
673 if (tinfo->typeclass->name == declaredtype->name) {
677 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
678 stset->subtyperefs[0].cls = tinfo->typeclass;
679 stset->subtyperefs[1].any = NULL; /* terminate */
686 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
691 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
695 unresolved_field *ref;
696 constant_FMIref *fieldref = NULL;
697 stackelement *instanceslot = NULL;
700 typeinfo *tip = NULL;
704 fprintf(stderr,"create_unresolved_field\n");
705 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
706 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
707 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
710 ref = NEW(unresolved_field);
712 ref->referermethod = refmethod;
714 switch (iptr[0].opc) {
716 ref->flags |= RESOLVE_PUTFIELD;
717 instanceslot = stack->prev;
718 tip = &(stack->typeinfo);
719 fieldref = (constant_FMIref *) iptr[0].val.a;
722 case ICMD_PUTFIELDCONST:
723 ref->flags |= RESOLVE_PUTFIELD;
724 instanceslot = stack;
725 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
729 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
730 fieldref = (constant_FMIref *) iptr[0].val.a;
731 tip = &(stack->typeinfo);
734 case ICMD_PUTSTATICCONST:
735 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
736 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
740 instanceslot = stack;
741 fieldref = (constant_FMIref *) iptr[0].val.a;
745 ref->flags |= RESOLVE_STATIC;
746 fieldref = (constant_FMIref *) iptr[0].val.a;
750 RESOLVE_ASSERT(fieldref);
751 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
752 fd = fieldref->parseddesc.fd;
756 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
757 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
758 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
759 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
761 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
764 ref->fieldref = fieldref;
766 /* record subtype constraints for the instance type, if any */
769 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
771 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
772 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
774 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
775 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
776 : refmethod->class; /* XXX classrefs */
777 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
778 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
782 insttip = &(instanceslot->typeinfo);
784 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
785 &(ref->instancetypes),insttip,fieldref->classref))
789 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
792 /* record subtype constraints for the value type, if any */
794 if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
796 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
798 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
799 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
802 TYPEINFO_INIT_NULLTYPE(tinfo);
804 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
805 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
809 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
816 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
820 unresolved_method *ref;
821 constant_FMIref *methodref;
822 stackelement *instanceslot = NULL;
829 methodref = (constant_FMIref *) iptr[0].val.a;
830 RESOLVE_ASSERT(methodref);
831 md = methodref->parseddesc.md;
835 fprintf(stderr,"create_unresolved_method\n");
836 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
837 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
838 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
839 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
840 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
841 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
842 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
845 ref = NEW(unresolved_method);
847 ref->referermethod = refmethod;
848 ref->methodref = methodref;
849 ref->paramconstraints = NULL;
851 switch (iptr[0].opc) {
852 case ICMD_INVOKESTATIC:
853 ref->flags |= RESOLVE_STATIC;
855 case ICMD_INVOKEVIRTUAL:
856 case ICMD_INVOKESPECIAL:
857 case ICMD_INVOKEINTERFACE:
860 RESOLVE_ASSERT(false);
863 if ((ref->flags & RESOLVE_STATIC) == 0) {
864 /* find the instance slot under all the parameter slots on the stack */
865 instanceslot = stack;
866 for (i=0; i<md->paramcount; ++i)
867 instanceslot = instanceslot->prev;
870 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
872 /* record subtype constraints for the instance type, if any */
876 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
878 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
879 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
881 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
882 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
883 : refmethod->class; /* XXX classrefs */
884 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
885 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
889 tip = &(instanceslot->typeinfo);
891 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
892 &(ref->instancetypes),tip,methodref->classref))
896 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
899 /* record subtype constraints for the parameter types, if any */
901 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
902 type = md->paramtypes[i].type;
904 RESOLVE_ASSERT(param);
905 RESOLVE_ASSERT(type == param->type);
907 if (type == TYPE_ADR) {
908 if (!ref->paramconstraints) {
909 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
910 for (j=md->paramcount-1; j>i; --j)
911 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
913 RESOLVE_ASSERT(ref->paramconstraints);
914 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
915 ref->paramconstraints + i,&(param->typeinfo),
916 md->paramtypes[i].classref))
920 if (ref->paramconstraints)
921 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
928 /******************************************************************************/
930 /******************************************************************************/
933 unresolved_subtype_set_free_list(classref_or_classinfo *list)
936 classref_or_classinfo *p = list;
938 /* this is silly. we *only* need to count the elements for MFREE */
941 MFREE(list,classref_or_classinfo,(p - list));
945 /* unresolved_field_free *******************************************************
947 Free the memory used by an unresolved_field
950 ref..............the unresolved_field
952 *******************************************************************************/
955 unresolved_field_free(unresolved_field *ref)
959 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
960 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
961 FREE(ref,unresolved_field);
964 /* unresolved_method_free ******************************************************
966 Free the memory used by an unresolved_method
969 ref..............the unresolved_method
971 *******************************************************************************/
974 unresolved_method_free(unresolved_method *ref)
978 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
979 if (ref->paramconstraints) {
981 int count = ref->methodref->parseddesc.md->paramcount;
983 for (i=0; i<count; ++i)
984 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
985 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
987 FREE(ref,unresolved_method);
990 /******************************************************************************/
992 /******************************************************************************/
994 /* unresolved_subtype_set_debug_dump *******************************************
996 Print debug info for unresolved_subtype_set to stream
999 stset............the unresolved_subtype_set
1000 file.............the stream
1002 *******************************************************************************/
1005 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1007 classref_or_classinfo *p;
1009 if (SUBTYPESET_IS_EMPTY(*stset)) {
1010 fprintf(file," (empty)\n");
1013 p = stset->subtyperefs;
1014 for (;p->any; ++p) {
1015 if (IS_CLASSREF(*p)) {
1016 fprintf(file," ref: ");
1017 utf_fprint(file,p->ref->name);
1020 fprintf(file," cls: ");
1021 utf_fprint(file,p->cls->name);
1028 /* unresolved_field_debug_dump *************************************************
1030 Print debug info for unresolved_field to stream
1033 ref..............the unresolved_field
1034 file.............the stream
1036 *******************************************************************************/
1039 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1041 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1043 fprintf(file," referer : ");
1044 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1045 fprintf(file," refmethod : ");
1046 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1047 fprintf(file," refmethodd : ");
1048 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1049 fprintf(file," classname : ");
1050 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1051 fprintf(file," name : ");
1052 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1053 fprintf(file," descriptor: ");
1054 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1055 fprintf(file," parseddesc: ");
1056 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1057 fprintf(file," flags : %04x\n",ref->flags);
1058 fprintf(file," instancetypes:\n");
1059 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1060 fprintf(file," valueconstraints:\n");
1061 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1065 /* unresolved_method_debug_dump ************************************************
1067 Print debug info for unresolved_method to stream
1070 ref..............the unresolved_method
1071 file.............the stream
1073 *******************************************************************************/
1076 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1080 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1082 fprintf(file," referer : ");
1083 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1084 fprintf(file," refmethod : ");
1085 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1086 fprintf(file," refmethodd : ");
1087 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1088 fprintf(file," classname : ");
1089 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1090 fprintf(file," name : ");
1091 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1092 fprintf(file," descriptor: ");
1093 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1094 fprintf(file," parseddesc: ");
1095 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1096 fprintf(file," flags : %04x\n",ref->flags);
1097 fprintf(file," instancetypes:\n");
1098 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1099 fprintf(file," paramconstraints:\n");
1100 if (ref->paramconstraints) {
1101 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1102 fprintf(file," param %d:\n",i);
1103 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1107 fprintf(file," (empty)\n");
1113 * These are local overrides for various environment variables in Emacs.
1114 * Please do not remove this and leave it at the end of the file, where
1115 * Emacs will automagically detect them.
1116 * ---------------------------------------------------------------------
1119 * indent-tabs-mode: t
1123 * vim:noexpandtab:sw=4:ts=4: