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 2224 2005-04-05 20:36:07Z edwin $
38 #include "mm/memory.h"
39 #include "vm/resolve.h"
40 #include "vm/access.h"
41 #include "vm/classcache.h"
42 #include "vm/exceptions.h"
43 #include "vm/loader.h"
44 #include "vm/linker.h"
45 #include "vm/classcache.h"
46 #include "vm/descriptor.h"
47 #include "vm/jit/jit.h"
48 #include "vm/jit/verify/typeinfo.h"
51 /******************************************************************************/
53 /******************************************************************************/
55 /*#define RESOLVE_VERBOSE*/
62 #define RESOLVE_ASSERT(cond) assert(cond)
64 #define RESOLVE_ASSERT(cond)
67 /******************************************************************************/
68 /* CLASS RESOLUTION */
69 /******************************************************************************/
71 /* resolve symbolic class reference -- see resolve.h */
73 resolve_class_from_name(classinfo *referer,methodinfo *refmethod,
78 classinfo *cls = NULL;
82 RESOLVE_ASSERT(result);
83 RESOLVE_ASSERT(referer);
84 RESOLVE_ASSERT(classname);
85 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
89 #ifdef RESOLVE_VERBOSE
90 fprintf(stderr,"resolve_class_from_name(");
91 utf_fprint(stderr,referer->name);
93 utf_fprint(stderr,classname);
94 fprintf(stderr,")\n");
97 /* lookup if this class has already been loaded */
98 cls = classcache_lookup(referer->classloader,classname);
100 #ifdef RESOLVE_VERBOSE
101 fprintf(stderr," lookup result: %p\n",(void*)cls);
105 /* resolve array types */
106 if (classname->text[0] == '[') {
107 utf_ptr = classname->text + 1;
108 len = classname->blength - 1;
109 /* classname is an array type name */
116 /* the component type is a reference type */
117 /* resolve the component type */
118 if (!resolve_class_from_name(referer,refmethod,
119 utf_new(utf_ptr,len),
121 return false; /* exception */
123 RESOLVE_ASSERT(mode == resolveLazy);
124 return true; /* be lazy */
126 /* create the array class */
127 cls = class_array_of(cls,false);
129 return false; /* exception */
133 /* the class has not been loaded, yet */
134 if (mode == resolveLazy)
135 return true; /* be lazy */
138 #ifdef RESOLVE_VERBOSE
139 fprintf(stderr," loading...\n");
144 if (!load_class_from_classloader(classname,referer->classloader,&cls))
145 return false; /* exception */
149 /* the class is now loaded */
151 RESOLVE_ASSERT(cls->loaded);
153 #ifdef RESOLVE_VERBOSE
154 fprintf(stderr," checking access rights...\n");
157 /* check access rights of referer to refered class */
158 if (!is_accessible_class(referer,cls)) {
159 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
160 "class is not accessible XXX add message");
161 return false; /* exception */
164 /* resolution succeeds */
165 #ifdef RESOLVE_VERBOSE
166 fprintf(stderr," success.\n");
173 resolve_classref(methodinfo *refmethod,
174 constant_classref *ref,
179 return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
183 resolve_classref_or_classinfo(methodinfo *refmethod,
184 classref_or_classinfo cls,
191 RESOLVE_ASSERT(cls.any);
192 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
193 RESOLVE_ASSERT(result);
195 #ifdef RESOLVE_VERBOSE
196 fprintf(stderr,"resolve_classref_or_classinfo(");
197 utf_fprint(stderr,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
198 fprintf(stderr,",%i,%i)\n",mode,link);
203 if (IS_CLASSREF(cls)) {
204 /* we must resolve this reference */
205 if (!resolve_class_from_name(cls.ref->referer,refmethod,cls.ref->name,
207 return false; /* exception */
210 /* cls has already been resolved */
212 RESOLVE_ASSERT(c->loaded);
214 RESOLVE_ASSERT(c || (mode == resolveLazy));
217 return true; /* be lazy */
220 RESOLVE_ASSERT(c->loaded);
225 return false; /* exception */
226 RESOLVE_ASSERT(c->linked);
235 resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
240 RESOLVE_ASSERT(result);
244 #ifdef RESOLVE_VERBOSE
245 fprintf(stderr,"resolve_class_from_typedesc(");
246 descriptor_debug_print_typedesc(stderr,d);
247 fprintf(stderr,",%i)\n",link);
251 /* a reference type */
252 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
253 resolveEager,link,&cls))
254 return false; /* exception */
257 /* a primitive type */
258 cls = primitivetype_table[d->decltype].class_primitive;
259 RESOLVE_ASSERT(cls->loaded);
261 if (!link_class(cls))
262 return false; /* exception */
265 RESOLVE_ASSERT(cls->loaded);
266 RESOLVE_ASSERT(!link || cls->linked);
268 #ifdef RESOLVE_VERBOSE
269 fprintf(stderr," result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
276 /******************************************************************************/
277 /* SUBTYPE SET CHECKS */
278 /******************************************************************************/
280 /* for documentation see resolve.h */
282 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
283 unresolved_subtype_set *ref,
284 classref_or_classinfo typeref,
290 classref_or_classinfo *setp;
296 RESOLVE_ASSERT(referer);
298 RESOLVE_ASSERT(typeref.any);
299 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
300 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
302 #ifdef RESOLVE_VERBOSE
303 fprintf(stderr,"resolve_and_check_subtype_set\n");
304 unresolved_subtype_set_debug_dump(ref,stderr);
305 if (IS_CLASSREF(typeref)) {
306 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
309 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
311 fprintf(stderr,"\n");
314 setp = ref->subtyperefs;
316 /* an empty set of tests always succeeds */
317 if (!setp || !setp->any) {
326 /* first resolve the type if necessary */
327 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
328 return false; /* exception */
330 return true; /* be lazy */
332 RESOLVE_ASSERT(type);
333 RESOLVE_ASSERT(type->loaded);
334 RESOLVE_ASSERT(type->linked);
335 TYPEINFO_INIT_CLASSINFO(typeti,type);
337 for (; setp->any; ++setp) {
338 /* first resolve the set member if necessary */
339 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
340 return false; /* exception */
342 return true; /* be lazy */
344 RESOLVE_ASSERT(result);
345 RESOLVE_ASSERT(result->loaded);
346 RESOLVE_ASSERT(result->linked);
348 #ifdef RESOLVE_VERBOSE
349 fprintf(stderr,"performing subclass test:\n");
350 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
351 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
352 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
355 /* now check the subtype relationship */
356 TYPEINFO_INIT_CLASSINFO(resultti,result);
358 /* we must test against `true` because `MAYBE` is also != 0 */
359 if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
360 #ifdef RESOLVE_VERBOSE
361 fprintf(stderr,"reversed subclass test failed\n");
367 /* we must test against `true` because `MAYBE` is also != 0 */
368 if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
369 #ifdef RESOLVE_VERBOSE
370 fprintf(stderr,"subclass test failed\n");
383 if (error == resolveIllegalAccessError)
384 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
385 "illegal access to protected member XXX add message");
387 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
388 "subtype constraint violated XXX add message");
389 return false; /* exception */
392 /******************************************************************************/
393 /* CLASS RESOLUTION */
394 /******************************************************************************/
396 /* for documentation see resolve.h */
398 resolve_class(unresolved_class *ref,
406 RESOLVE_ASSERT(result);
407 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
411 #ifdef RESOLVE_VERBOSE
412 unresolved_class_debug_dump(ref,stderr);
415 /* first we must resolve the class */
416 if (!resolve_classref(ref->referermethod,
417 ref->classref,mode,true,&cls))
419 /* the class reference could not be resolved */
420 return false; /* exception */
423 return true; /* be lazy */
426 RESOLVE_ASSERT(cls->loaded && cls->linked);
428 /* now we check the subtype constraints */
429 if (!resolve_and_check_subtype_set(ref->classref->referer,ref->referermethod,
430 &(ref->subtypeconstraints),
431 CLASSREF_OR_CLASSINFO(cls),
434 resolveLinkageError,&checked))
436 return false; /* exception */
439 return true; /* be lazy */
446 /******************************************************************************/
447 /* FIELD RESOLUTION */
448 /******************************************************************************/
450 /* for documentation see resolve.h */
452 resolve_field(unresolved_field *ref,
457 classinfo *container;
459 constant_classref *fieldtyperef;
464 RESOLVE_ASSERT(result);
465 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
469 #ifdef RESOLVE_VERBOSE
470 unresolved_field_debug_dump(ref,stderr);
473 /* the class containing the reference */
474 referer = ref->fieldref->classref->referer;
475 RESOLVE_ASSERT(referer);
477 /* first we must resolve the class containg the field */
478 if (!resolve_class_from_name(referer,ref->referermethod,
479 ref->fieldref->classref->name,mode,&container))
481 /* the class reference could not be resolved */
482 return false; /* exception */
485 return true; /* be lazy */
487 RESOLVE_ASSERT(container);
488 RESOLVE_ASSERT(container->loaded && container->linked);
490 /* now we must find the declaration of the field in `container`
491 * or one of its superclasses */
493 #ifdef RESOLVE_VERBOSE
494 fprintf(stderr," resolving field in class...\n");
497 fi = class_resolvefield(container,
498 ref->fieldref->name,ref->fieldref->descriptor,
501 return false; /* exception */
503 /* { the field reference has been resolved } */
504 declarer = fi->class;
505 RESOLVE_ASSERT(declarer);
506 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
508 #ifdef RESOLVE_VERBOSE
509 fprintf(stderr," checking static...\n");
513 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
514 /* a static field is accessed via an instance, or vice versa */
515 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
516 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
517 : "instance field accessed without instance");
518 return false; /* exception */
521 /* for non-static accesses we have to check the constraints on the instance type */
522 if ((ref->flags & RESOLVE_STATIC) == 0) {
523 #ifdef RESOLVE_VERBOSE
524 fprintf(stderr," checking instance types...\n");
527 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
528 &(ref->instancetypes),
529 CLASSREF_OR_CLASSINFO(container),
532 resolveLinkageError,&checked))
534 return false; /* exception */
537 return true; /* be lazy */
540 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
542 /* for PUT* instructions we have to check the constraints on the value type */
543 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
544 RESOLVE_ASSERT(fieldtyperef);
545 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
546 /* check subtype constraints */
547 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
548 &(ref->valueconstraints),
549 CLASSREF_OR_CLASSINFO(fieldtyperef),
552 resolveLinkageError,&checked))
554 return false; /* exception */
557 return true; /* be lazy */
561 /* check access rights */
562 if (!is_accessible_member(referer,declarer,fi->flags)) {
563 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
564 "field is not accessible XXX add message");
565 return false; /* exception */
568 /* check protected access */
569 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
570 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
571 &(ref->instancetypes),
572 CLASSREF_OR_CLASSINFO(referer),
575 resolveIllegalAccessError,&checked))
577 return false; /* exception */
580 return true; /* be lazy */
583 /* impose loading constraint on field type */
584 if (fi->type == TYPE_ADR) {
585 RESOLVE_ASSERT(fieldtyperef);
586 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
588 return false; /* exception */
596 /******************************************************************************/
597 /* METHOD RESOLUTION */
598 /******************************************************************************/
600 /* for documentation see resolve.h */
602 resolve_method(unresolved_method *ref,
607 classinfo *container;
610 typedesc *paramtypes;
616 RESOLVE_ASSERT(result);
617 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
619 #ifdef RESOLVE_VERBOSE
620 unresolved_method_debug_dump(ref,stderr);
625 /* the class containing the reference */
626 referer = ref->methodref->classref->referer;
627 RESOLVE_ASSERT(referer);
629 /* first we must resolve the class containg the method */
630 if (!resolve_class_from_name(referer,ref->referermethod,
631 ref->methodref->classref->name,mode,&container))
633 /* the class reference could not be resolved */
634 return false; /* exception */
637 return true; /* be lazy */
639 RESOLVE_ASSERT(container);
641 /* now we must find the declaration of the method in `container`
642 * or one of its superclasses */
644 if ((container->flags & ACC_INTERFACE) != 0) {
645 mi = class_resolveinterfacemethod(container,
646 ref->methodref->name,ref->methodref->descriptor,
650 mi = class_resolveclassmethod(container,
651 ref->methodref->name,ref->methodref->descriptor,
655 return false; /* exception */ /* XXX set exceptionptr? */
656 method_descriptor2types(mi);
658 /* { the method reference has been resolved } */
659 declarer = mi->class;
660 RESOLVE_ASSERT(declarer);
663 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
664 /* a static method is accessed via an instance, or vice versa */
665 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
666 (mi->flags & ACC_STATIC) ? "static method called via instance"
667 : "instance method called without instance");
668 return false; /* exception */
671 /* for non-static methods we have to check the constraints on the instance type */
672 if ((ref->flags & RESOLVE_STATIC) == 0) {
673 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
674 &(ref->instancetypes),
675 CLASSREF_OR_CLASSINFO(container),
678 resolveLinkageError,&checked))
680 return false; /* exception */
683 return true; /* be lazy */
690 /* check subtype constraints for TYPE_ADR parameters */
691 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
692 paramtypes = ref->methodref->parseddesc.md->paramtypes;
694 for (i=0; i<(mi->paramcount-instancecount); ++i) {
695 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
696 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
697 if (ref->paramconstraints) {
698 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
699 ref->paramconstraints + i,
700 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
703 resolveLinkageError,&checked))
705 return false; /* exception */
708 return true; /* be lazy */
713 /* check access rights */
714 if (!is_accessible_member(referer,declarer,mi->flags)) {
715 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
716 "method is not accessible XXX add message");
717 return false; /* exception */
720 /* check protected access */
721 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
722 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
723 &(ref->instancetypes),
724 CLASSREF_OR_CLASSINFO(referer),
727 resolveIllegalAccessError,&checked))
729 return false; /* exception */
732 return true; /* be lazy */
735 /* impose loading constraints on parameters (including instance) */
736 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
737 for (i=0; i<mi->paramcount; ++i) {
738 if (mi->paramtypes[i] == TYPE_ADR) {
741 if (i < instancecount)
742 name = container->name; /* XXX should this be declarer->name? */
744 name = paramtypes[i].classref->name;
746 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
747 return false; /* exception */
751 /* impose loading constraing onto return type */
752 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
753 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
754 ref->methodref->parseddesc.md->returntype.classref->name))
755 return false; /* exception */
763 /******************************************************************************/
764 /* CREATING THE DATA STRUCTURES */
765 /******************************************************************************/
768 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
769 unresolved_subtype_set *stset,typeinfo *tinfo,
770 constant_classref *declaredtype)
775 RESOLVE_ASSERT(stset);
776 RESOLVE_ASSERT(tinfo);
778 #ifdef RESOLVE_VERBOSE
779 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
780 #ifdef TYPEINFO_DEBUG
781 /*typeinfo_print(stderr,tinfo,4);*/
782 fprintf(stderr,"\n");
784 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
785 fprintf(stderr,"\n");
788 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
789 *exceptionptr = new_verifyerror(refmethod,
790 "Invalid use of returnAddress");
794 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
795 *exceptionptr = new_verifyerror(refmethod,
796 "Invalid use of uninitialized object");
800 /* the nulltype is always assignable (XXX for reversed?) */
801 if (TYPEINFO_IS_NULLTYPE(*tinfo))
804 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
805 if (declaredtype->name == utf_java_lang_Object
806 && referer->classloader == NULL)
812 count = tinfo->merged->count;
813 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
814 for (i=0; i<count; ++i) {
815 stset->subtyperefs[i] = tinfo->merged->list[i];
817 stset->subtyperefs[count].any = NULL; /* terminate */
820 if ((IS_CLASSREF(tinfo->typeclass)
821 ? tinfo->typeclass.ref->name
822 : tinfo->typeclass.cls->name) == declaredtype->name)
827 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
828 stset->subtyperefs[0] = tinfo->typeclass;
829 stset->subtyperefs[1].any = NULL; /* terminate */
836 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
841 create_unresolved_class(methodinfo *refmethod,
842 constant_classref *classref,
845 unresolved_class *ref;
849 #ifdef RESOLVE_VERBOSE
850 fprintf(stderr,"create_unresolved_class\n");
851 fprintf(stderr," referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
852 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
853 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
854 fprintf(stderr," name : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
857 ref = NEW(unresolved_class);
858 ref->classref = classref;
859 ref->referermethod = refmethod;
862 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
863 &(ref->subtypeconstraints),valuetype,classref))
867 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
874 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
878 unresolved_field *ref;
879 constant_FMIref *fieldref = NULL;
880 stackelement *instanceslot = NULL;
883 typeinfo *tip = NULL;
886 #ifdef RESOLVE_VERBOSE
887 fprintf(stderr,"create_unresolved_field\n");
888 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
889 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
890 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
893 ref = NEW(unresolved_field);
895 ref->referermethod = refmethod;
897 switch (iptr[0].opc) {
899 ref->flags |= RESOLVE_PUTFIELD;
901 instanceslot = stack->prev;
902 tip = &(stack->typeinfo);
904 fieldref = (constant_FMIref *) iptr[0].val.a;
907 case ICMD_PUTFIELDCONST:
908 ref->flags |= RESOLVE_PUTFIELD;
909 if (stack) instanceslot = stack;
910 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
914 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
915 fieldref = (constant_FMIref *) iptr[0].val.a;
916 if (stack) tip = &(stack->typeinfo);
919 case ICMD_PUTSTATICCONST:
920 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
921 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
925 if (stack) instanceslot = stack;
926 fieldref = (constant_FMIref *) iptr[0].val.a;
930 ref->flags |= RESOLVE_STATIC;
931 fieldref = (constant_FMIref *) iptr[0].val.a;
935 RESOLVE_ASSERT(fieldref);
936 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
937 fd = fieldref->parseddesc.fd;
940 #ifdef RESOLVE_VERBOSE
941 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
942 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
943 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
944 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
946 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
949 ref->fieldref = fieldref;
951 /* record subtype constraints for the instance type, if any */
954 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
956 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
957 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
959 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
960 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
961 : refmethod->class; /* XXX classrefs */
962 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
963 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
967 insttip = &(instanceslot->typeinfo);
969 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
970 &(ref->instancetypes),insttip,fieldref->classref))
974 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
977 /* record subtype constraints for the value type, if any */
979 if (stack && type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
981 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
983 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
984 RESOLVE_ASSERT(class_java_lang_String);
985 RESOLVE_ASSERT(class_java_lang_String->loaded);
986 RESOLVE_ASSERT(class_java_lang_String->linked);
987 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
990 TYPEINFO_INIT_NULLTYPE(tinfo);
992 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
993 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
997 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1004 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
1006 stackelement *stack)
1008 unresolved_method *ref;
1009 constant_FMIref *methodref;
1010 stackelement *instanceslot = NULL;
1011 stackelement *param;
1017 methodref = (constant_FMIref *) iptr[0].val.a;
1018 RESOLVE_ASSERT(methodref);
1019 md = methodref->parseddesc.md;
1022 #ifdef RESOLVE_VERBOSE
1023 fprintf(stderr,"create_unresolved_method\n");
1024 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1025 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1026 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1027 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1028 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1029 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1030 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1033 ref = NEW(unresolved_method);
1035 ref->referermethod = refmethod;
1036 ref->methodref = methodref;
1037 ref->paramconstraints = NULL;
1039 switch (iptr[0].opc) {
1040 case ICMD_INVOKESTATIC:
1041 ref->flags |= RESOLVE_STATIC;
1043 case ICMD_INVOKEVIRTUAL:
1044 case ICMD_INVOKESPECIAL:
1045 case ICMD_INVOKEINTERFACE:
1048 RESOLVE_ASSERT(false);
1051 if (stack && (ref->flags & RESOLVE_STATIC) == 0) {
1052 /* find the instance slot under all the parameter slots on the stack */
1053 instanceslot = stack;
1054 for (i=0; i<md->paramcount; ++i)
1055 instanceslot = instanceslot->prev;
1058 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1060 /* record subtype constraints for the instance type, if any */
1064 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
1066 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
1067 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1068 { /* XXX clean up */
1069 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1070 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
1071 : refmethod->class; /* XXX classrefs */
1072 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
1073 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1077 tip = &(instanceslot->typeinfo);
1079 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1080 &(ref->instancetypes),tip,methodref->classref))
1084 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1087 /* record subtype constraints for the parameter types, if any */
1090 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
1091 type = md->paramtypes[i].type;
1093 RESOLVE_ASSERT(param);
1094 RESOLVE_ASSERT(type == param->type);
1096 if (type == TYPE_ADR) {
1097 if (!ref->paramconstraints) {
1098 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1099 for (j=md->paramcount-1; j>i; --j)
1100 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1102 RESOLVE_ASSERT(ref->paramconstraints);
1103 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1104 ref->paramconstraints + i,&(param->typeinfo),
1105 md->paramtypes[i].classref))
1109 if (ref->paramconstraints)
1110 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1118 /******************************************************************************/
1119 /* FREEING MEMORY */
1120 /******************************************************************************/
1123 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1126 classref_or_classinfo *p = list;
1128 /* this is silly. we *only* need to count the elements for MFREE */
1131 MFREE(list,classref_or_classinfo,(p - list));
1135 /* unresolved_class_free *******************************************************
1137 Free the memory used by an unresolved_class
1140 ref..............the unresolved_class
1142 *******************************************************************************/
1145 unresolved_class_free(unresolved_class *ref)
1147 RESOLVE_ASSERT(ref);
1149 unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
1150 FREE(ref,unresolved_class);
1153 /* unresolved_field_free *******************************************************
1155 Free the memory used by an unresolved_field
1158 ref..............the unresolved_field
1160 *******************************************************************************/
1163 unresolved_field_free(unresolved_field *ref)
1165 RESOLVE_ASSERT(ref);
1167 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1168 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1169 FREE(ref,unresolved_field);
1172 /* unresolved_method_free ******************************************************
1174 Free the memory used by an unresolved_method
1177 ref..............the unresolved_method
1179 *******************************************************************************/
1182 unresolved_method_free(unresolved_method *ref)
1184 RESOLVE_ASSERT(ref);
1186 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1187 if (ref->paramconstraints) {
1189 int count = ref->methodref->parseddesc.md->paramcount;
1191 for (i=0; i<count; ++i)
1192 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1193 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1195 FREE(ref,unresolved_method);
1198 /******************************************************************************/
1200 /******************************************************************************/
1202 /* unresolved_subtype_set_debug_dump *******************************************
1204 Print debug info for unresolved_subtype_set to stream
1207 stset............the unresolved_subtype_set
1208 file.............the stream
1210 *******************************************************************************/
1213 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1215 classref_or_classinfo *p;
1217 if (SUBTYPESET_IS_EMPTY(*stset)) {
1218 fprintf(file," (empty)\n");
1221 p = stset->subtyperefs;
1222 for (;p->any; ++p) {
1223 if (IS_CLASSREF(*p)) {
1224 fprintf(file," ref: ");
1225 utf_fprint(file,p->ref->name);
1228 fprintf(file," cls: ");
1229 utf_fprint(file,p->cls->name);
1236 /* unresolved_class_debug_dump *************************************************
1238 Print debug info for unresolved_class to stream
1241 ref..............the unresolved_class
1242 file.............the stream
1244 *******************************************************************************/
1247 unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
1249 fprintf(file,"unresolved_class(%p):\n",(void *)ref);
1251 fprintf(file," referer : ");
1252 utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
1253 fprintf(file," refmethod : ");
1254 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1255 fprintf(file," refmethodd : ");
1256 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1257 fprintf(file," classname : ");
1258 utf_fprint(file,ref->classref->name); fputc('\n',file);
1259 fprintf(file," subtypeconstraints:\n");
1260 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
1264 /* unresolved_field_debug_dump *************************************************
1266 Print debug info for unresolved_field to stream
1269 ref..............the unresolved_field
1270 file.............the stream
1272 *******************************************************************************/
1275 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1277 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1279 fprintf(file," referer : ");
1280 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1281 fprintf(file," refmethod : ");
1282 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1283 fprintf(file," refmethodd : ");
1284 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1285 fprintf(file," classname : ");
1286 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1287 fprintf(file," name : ");
1288 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1289 fprintf(file," descriptor: ");
1290 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1291 fprintf(file," parseddesc: ");
1292 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1293 fprintf(file," flags : %04x\n",ref->flags);
1294 fprintf(file," instancetypes:\n");
1295 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1296 fprintf(file," valueconstraints:\n");
1297 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1301 /* unresolved_method_debug_dump ************************************************
1303 Print debug info for unresolved_method to stream
1306 ref..............the unresolved_method
1307 file.............the stream
1309 *******************************************************************************/
1312 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1316 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1318 fprintf(file," referer : ");
1319 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1320 fprintf(file," refmethod : ");
1321 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1322 fprintf(file," refmethodd : ");
1323 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1324 fprintf(file," classname : ");
1325 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1326 fprintf(file," name : ");
1327 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1328 fprintf(file," descriptor: ");
1329 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1330 fprintf(file," parseddesc: ");
1331 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1332 fprintf(file," flags : %04x\n",ref->flags);
1333 fprintf(file," instancetypes:\n");
1334 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1335 fprintf(file," paramconstraints:\n");
1336 if (ref->paramconstraints) {
1337 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1338 fprintf(file," param %d:\n",i);
1339 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1343 fprintf(file," (empty)\n");
1349 * These are local overrides for various environment variables in Emacs.
1350 * Please do not remove this and leave it at the end of the file, where
1351 * Emacs will automagically detect them.
1352 * ---------------------------------------------------------------------
1355 * indent-tabs-mode: t
1359 * vim:noexpandtab:sw=4:ts=4: