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 2227 2005-04-05 23:00:37Z 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,
79 classinfo *cls = NULL;
83 RESOLVE_ASSERT(result);
84 RESOLVE_ASSERT(referer);
85 RESOLVE_ASSERT(classname);
86 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
90 #ifdef RESOLVE_VERBOSE
91 fprintf(stderr,"resolve_class_from_name(");
92 utf_fprint(stderr,referer->name);
94 utf_fprint(stderr,classname);
95 fprintf(stderr,")\n");
98 /* lookup if this class has already been loaded */
99 cls = classcache_lookup(referer->classloader,classname);
101 #ifdef RESOLVE_VERBOSE
102 fprintf(stderr," lookup result: %p\n",(void*)cls);
106 /* resolve array types */
107 if (classname->text[0] == '[') {
108 utf_ptr = classname->text + 1;
109 len = classname->blength - 1;
110 /* classname is an array type name */
117 /* the component type is a reference type */
118 /* resolve the component type */
119 if (!resolve_class_from_name(referer,refmethod,
120 utf_new(utf_ptr,len),
122 return false; /* exception */
124 RESOLVE_ASSERT(mode == resolveLazy);
125 return true; /* be lazy */
127 /* create the array class */
128 cls = class_array_of(cls,false);
130 return false; /* exception */
134 /* the class has not been loaded, yet */
135 if (mode == resolveLazy)
136 return true; /* be lazy */
139 #ifdef RESOLVE_VERBOSE
140 fprintf(stderr," loading...\n");
145 if (!load_class_from_classloader(classname,referer->classloader,&cls))
146 return false; /* exception */
150 /* the class is now loaded */
152 RESOLVE_ASSERT(cls->loaded);
154 #ifdef RESOLVE_VERBOSE
155 fprintf(stderr," checking access rights...\n");
158 /* check access rights of referer to refered class */
159 if (!is_accessible_class(referer,cls)) {
160 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
161 "class is not accessible XXX add message");
162 return false; /* exception */
165 /* link the class if necessary */
168 if (!link_class(cls))
169 return false; /* exception */
170 RESOLVE_ASSERT(cls->linked);
173 /* resolution succeeds */
174 #ifdef RESOLVE_VERBOSE
175 fprintf(stderr," success.\n");
182 resolve_classref(methodinfo *refmethod,
183 constant_classref *ref,
188 return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
192 resolve_classref_or_classinfo(methodinfo *refmethod,
193 classref_or_classinfo cls,
200 RESOLVE_ASSERT(cls.any);
201 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
202 RESOLVE_ASSERT(result);
204 #ifdef RESOLVE_VERBOSE
205 fprintf(stderr,"resolve_classref_or_classinfo(");
206 utf_fprint(stderr,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
207 fprintf(stderr,",%i,%i)\n",mode,link);
212 if (IS_CLASSREF(cls)) {
213 /* we must resolve this reference */
214 if (!resolve_class_from_name(cls.ref->referer,refmethod,cls.ref->name,
216 return false; /* exception */
219 /* cls has already been resolved */
221 RESOLVE_ASSERT(c->loaded);
223 RESOLVE_ASSERT(c || (mode == resolveLazy));
226 return true; /* be lazy */
229 RESOLVE_ASSERT(c->loaded);
234 return false; /* exception */
235 RESOLVE_ASSERT(c->linked);
244 resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
249 RESOLVE_ASSERT(result);
253 #ifdef RESOLVE_VERBOSE
254 fprintf(stderr,"resolve_class_from_typedesc(");
255 descriptor_debug_print_typedesc(stderr,d);
256 fprintf(stderr,",%i)\n",link);
260 /* a reference type */
261 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
262 resolveEager,link,&cls))
263 return false; /* exception */
266 /* a primitive type */
267 cls = primitivetype_table[d->decltype].class_primitive;
268 RESOLVE_ASSERT(cls->loaded);
270 if (!link_class(cls))
271 return false; /* exception */
274 RESOLVE_ASSERT(cls->loaded);
275 RESOLVE_ASSERT(!link || cls->linked);
277 #ifdef RESOLVE_VERBOSE
278 fprintf(stderr," result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
285 /******************************************************************************/
286 /* SUBTYPE SET CHECKS */
287 /******************************************************************************/
289 /* for documentation see resolve.h */
291 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
292 unresolved_subtype_set *ref,
293 classref_or_classinfo typeref,
299 classref_or_classinfo *setp;
305 RESOLVE_ASSERT(referer);
307 RESOLVE_ASSERT(typeref.any);
308 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
309 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
311 #ifdef RESOLVE_VERBOSE
312 fprintf(stderr,"resolve_and_check_subtype_set\n");
313 unresolved_subtype_set_debug_dump(ref,stderr);
314 if (IS_CLASSREF(typeref)) {
315 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
318 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
320 fprintf(stderr,"\n");
323 setp = ref->subtyperefs;
325 /* an empty set of tests always succeeds */
326 if (!setp || !setp->any) {
335 /* first resolve the type if necessary */
336 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
337 return false; /* exception */
339 return true; /* be lazy */
341 RESOLVE_ASSERT(type);
342 RESOLVE_ASSERT(type->loaded);
343 RESOLVE_ASSERT(type->linked);
344 TYPEINFO_INIT_CLASSINFO(typeti,type);
346 for (; setp->any; ++setp) {
347 /* first resolve the set member if necessary */
348 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
349 return false; /* exception */
351 return true; /* be lazy */
353 RESOLVE_ASSERT(result);
354 RESOLVE_ASSERT(result->loaded);
355 RESOLVE_ASSERT(result->linked);
357 #ifdef RESOLVE_VERBOSE
358 fprintf(stderr,"performing subclass test:\n");
359 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
360 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
361 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
364 /* now check the subtype relationship */
365 TYPEINFO_INIT_CLASSINFO(resultti,result);
367 /* we must test against `true` because `MAYBE` is also != 0 */
368 if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
369 #ifdef RESOLVE_VERBOSE
370 fprintf(stderr,"reversed subclass test failed\n");
376 /* we must test against `true` because `MAYBE` is also != 0 */
377 if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
378 #ifdef RESOLVE_VERBOSE
379 fprintf(stderr,"subclass test failed\n");
392 if (error == resolveIllegalAccessError)
393 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
394 "illegal access to protected member XXX add message");
396 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
397 "subtype constraint violated XXX add message");
398 return false; /* exception */
401 /******************************************************************************/
402 /* CLASS RESOLUTION */
403 /******************************************************************************/
405 /* for documentation see resolve.h */
407 resolve_class(unresolved_class *ref,
415 RESOLVE_ASSERT(result);
416 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
420 #ifdef RESOLVE_VERBOSE
421 unresolved_class_debug_dump(ref,stderr);
424 /* first we must resolve the class */
425 if (!resolve_classref(ref->referermethod,
426 ref->classref,mode,true,&cls))
428 /* the class reference could not be resolved */
429 return false; /* exception */
432 return true; /* be lazy */
435 RESOLVE_ASSERT(cls->loaded && cls->linked);
437 /* now we check the subtype constraints */
438 if (!resolve_and_check_subtype_set(ref->classref->referer,ref->referermethod,
439 &(ref->subtypeconstraints),
440 CLASSREF_OR_CLASSINFO(cls),
443 resolveLinkageError,&checked))
445 return false; /* exception */
448 return true; /* be lazy */
455 /******************************************************************************/
456 /* FIELD RESOLUTION */
457 /******************************************************************************/
459 /* for documentation see resolve.h */
461 resolve_field(unresolved_field *ref,
466 classinfo *container;
468 constant_classref *fieldtyperef;
473 RESOLVE_ASSERT(result);
474 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
478 #ifdef RESOLVE_VERBOSE
479 unresolved_field_debug_dump(ref,stderr);
482 /* the class containing the reference */
483 referer = ref->fieldref->classref->referer;
484 RESOLVE_ASSERT(referer);
486 /* first we must resolve the class containg the field */
487 if (!resolve_class_from_name(referer,ref->referermethod,
488 ref->fieldref->classref->name,mode,true,&container))
490 /* the class reference could not be resolved */
491 return false; /* exception */
494 return true; /* be lazy */
496 RESOLVE_ASSERT(container);
497 RESOLVE_ASSERT(container->loaded && container->linked);
499 /* now we must find the declaration of the field in `container`
500 * or one of its superclasses */
502 #ifdef RESOLVE_VERBOSE
503 fprintf(stderr," resolving field in class...\n");
506 fi = class_resolvefield(container,
507 ref->fieldref->name,ref->fieldref->descriptor,
510 return false; /* exception */
512 /* { the field reference has been resolved } */
513 declarer = fi->class;
514 RESOLVE_ASSERT(declarer);
515 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
517 #ifdef RESOLVE_VERBOSE
518 fprintf(stderr," checking static...\n");
522 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
523 /* a static field is accessed via an instance, or vice versa */
524 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
525 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
526 : "instance field accessed without instance");
527 return false; /* exception */
530 /* for non-static accesses we have to check the constraints on the instance type */
531 if ((ref->flags & RESOLVE_STATIC) == 0) {
532 #ifdef RESOLVE_VERBOSE
533 fprintf(stderr," checking instance types...\n");
536 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
537 &(ref->instancetypes),
538 CLASSREF_OR_CLASSINFO(container),
541 resolveLinkageError,&checked))
543 return false; /* exception */
546 return true; /* be lazy */
549 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
551 /* for PUT* instructions we have to check the constraints on the value type */
552 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
553 RESOLVE_ASSERT(fieldtyperef);
554 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
555 /* check subtype constraints */
556 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
557 &(ref->valueconstraints),
558 CLASSREF_OR_CLASSINFO(fieldtyperef),
561 resolveLinkageError,&checked))
563 return false; /* exception */
566 return true; /* be lazy */
570 /* check access rights */
571 if (!is_accessible_member(referer,declarer,fi->flags)) {
572 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
573 "field is not accessible XXX add message");
574 return false; /* exception */
577 /* check protected access */
578 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
579 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
580 &(ref->instancetypes),
581 CLASSREF_OR_CLASSINFO(referer),
584 resolveIllegalAccessError,&checked))
586 return false; /* exception */
589 return true; /* be lazy */
592 /* impose loading constraint on field type */
593 if (fi->type == TYPE_ADR) {
594 RESOLVE_ASSERT(fieldtyperef);
595 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
597 return false; /* exception */
605 /******************************************************************************/
606 /* METHOD RESOLUTION */
607 /******************************************************************************/
609 /* for documentation see resolve.h */
611 resolve_method(unresolved_method *ref,
616 classinfo *container;
619 typedesc *paramtypes;
625 RESOLVE_ASSERT(result);
626 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
628 #ifdef RESOLVE_VERBOSE
629 unresolved_method_debug_dump(ref,stderr);
634 /* the class containing the reference */
635 referer = ref->methodref->classref->referer;
636 RESOLVE_ASSERT(referer);
638 /* first we must resolve the class containg the method */
639 if (!resolve_class_from_name(referer,ref->referermethod,
640 ref->methodref->classref->name,mode,true,&container))
642 /* the class reference could not be resolved */
643 return false; /* exception */
646 return true; /* be lazy */
648 RESOLVE_ASSERT(container);
650 /* now we must find the declaration of the method in `container`
651 * or one of its superclasses */
653 if ((container->flags & ACC_INTERFACE) != 0) {
654 mi = class_resolveinterfacemethod(container,
655 ref->methodref->name,ref->methodref->descriptor,
659 mi = class_resolveclassmethod(container,
660 ref->methodref->name,ref->methodref->descriptor,
664 return false; /* exception */ /* XXX set exceptionptr? */
666 /* { the method reference has been resolved } */
667 declarer = mi->class;
668 RESOLVE_ASSERT(declarer);
671 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
672 /* a static method is accessed via an instance, or vice versa */
673 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
674 (mi->flags & ACC_STATIC) ? "static method called via instance"
675 : "instance method called without instance");
676 return false; /* exception */
679 /* for non-static methods we have to check the constraints on the instance type */
680 if ((ref->flags & RESOLVE_STATIC) == 0) {
681 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
682 &(ref->instancetypes),
683 CLASSREF_OR_CLASSINFO(container),
686 resolveLinkageError,&checked))
688 return false; /* exception */
691 return true; /* be lazy */
698 /* check subtype constraints for TYPE_ADR parameters */
699 RESOLVE_ASSERT(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
700 paramtypes = mi->parseddesc->paramtypes;
702 for (i=0; i<mi->parseddesc->paramcount; ++i) {
703 if (paramtypes[i].type == TYPE_ADR) {
704 if (ref->paramconstraints) {
705 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
706 ref->paramconstraints + i,
707 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
710 resolveLinkageError,&checked))
712 return false; /* exception */
715 return true; /* be lazy */
720 /* check access rights */
721 if (!is_accessible_member(referer,declarer,mi->flags)) {
722 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
723 "method is not accessible XXX add message");
724 return false; /* exception */
727 /* check protected access */
728 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
729 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
730 &(ref->instancetypes),
731 CLASSREF_OR_CLASSINFO(referer),
734 resolveIllegalAccessError,&checked))
736 return false; /* exception */
739 return true; /* be lazy */
742 /* impose loading constraints on parameters (including instance) */
743 paramtypes = mi->parseddesc->paramtypes - instancecount;
744 for (i=0; i<mi->parseddesc->paramcount + instancecount; ++i) {
745 if (i<instancecount || paramtypes[i].type == TYPE_ADR) {
748 if (i < instancecount)
749 name = container->name; /* XXX should this be declarer->name? */
751 name = paramtypes[i].classref->name;
753 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
754 return false; /* exception */
758 /* impose loading constraing onto return type */
759 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
760 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
761 ref->methodref->parseddesc.md->returntype.classref->name))
762 return false; /* exception */
770 /******************************************************************************/
771 /* CREATING THE DATA STRUCTURES */
772 /******************************************************************************/
775 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
776 unresolved_subtype_set *stset,typeinfo *tinfo,
777 constant_classref *declaredtype)
782 RESOLVE_ASSERT(stset);
783 RESOLVE_ASSERT(tinfo);
785 #ifdef RESOLVE_VERBOSE
786 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
787 #ifdef TYPEINFO_DEBUG
788 /*typeinfo_print(stderr,tinfo,4);*/
789 fprintf(stderr,"\n");
791 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
792 fprintf(stderr,"\n");
795 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
796 *exceptionptr = new_verifyerror(refmethod,
797 "Invalid use of returnAddress");
801 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
802 *exceptionptr = new_verifyerror(refmethod,
803 "Invalid use of uninitialized object");
807 /* the nulltype is always assignable (XXX for reversed?) */
808 if (TYPEINFO_IS_NULLTYPE(*tinfo))
811 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
812 if (declaredtype->name == utf_java_lang_Object
813 && referer->classloader == NULL)
819 count = tinfo->merged->count;
820 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
821 for (i=0; i<count; ++i) {
822 stset->subtyperefs[i] = tinfo->merged->list[i];
824 stset->subtyperefs[count].any = NULL; /* terminate */
827 if ((IS_CLASSREF(tinfo->typeclass)
828 ? tinfo->typeclass.ref->name
829 : tinfo->typeclass.cls->name) == declaredtype->name)
834 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
835 stset->subtyperefs[0] = tinfo->typeclass;
836 stset->subtyperefs[1].any = NULL; /* terminate */
843 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
848 create_unresolved_class(methodinfo *refmethod,
849 constant_classref *classref,
852 unresolved_class *ref;
856 #ifdef RESOLVE_VERBOSE
857 fprintf(stderr,"create_unresolved_class\n");
858 fprintf(stderr," referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
859 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
860 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
861 fprintf(stderr," name : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
864 ref = NEW(unresolved_class);
865 ref->classref = classref;
866 ref->referermethod = refmethod;
869 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
870 &(ref->subtypeconstraints),valuetype,classref))
874 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
881 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
885 unresolved_field *ref;
886 constant_FMIref *fieldref = NULL;
887 stackelement *instanceslot = NULL;
890 typeinfo *tip = NULL;
893 #ifdef RESOLVE_VERBOSE
894 fprintf(stderr,"create_unresolved_field\n");
895 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
896 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
897 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
900 ref = NEW(unresolved_field);
902 ref->referermethod = refmethod;
904 switch (iptr[0].opc) {
906 ref->flags |= RESOLVE_PUTFIELD;
908 instanceslot = stack->prev;
909 tip = &(stack->typeinfo);
911 fieldref = (constant_FMIref *) iptr[0].val.a;
914 case ICMD_PUTFIELDCONST:
915 ref->flags |= RESOLVE_PUTFIELD;
916 if (stack) instanceslot = stack;
917 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
921 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
922 fieldref = (constant_FMIref *) iptr[0].val.a;
923 if (stack) tip = &(stack->typeinfo);
926 case ICMD_PUTSTATICCONST:
927 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
928 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
932 if (stack) instanceslot = stack;
933 fieldref = (constant_FMIref *) iptr[0].val.a;
937 ref->flags |= RESOLVE_STATIC;
938 fieldref = (constant_FMIref *) iptr[0].val.a;
942 RESOLVE_ASSERT(fieldref);
943 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
944 fd = fieldref->parseddesc.fd;
947 #ifdef RESOLVE_VERBOSE
948 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
949 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
950 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
951 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
953 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
956 ref->fieldref = fieldref;
958 /* record subtype constraints for the instance type, if any */
961 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
963 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
964 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
966 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
967 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
968 : refmethod->class; /* XXX classrefs */
969 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
970 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
974 insttip = &(instanceslot->typeinfo);
976 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
977 &(ref->instancetypes),insttip,fieldref->classref))
981 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
984 /* record subtype constraints for the value type, if any */
986 if (stack && type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
988 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
990 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
991 RESOLVE_ASSERT(class_java_lang_String);
992 RESOLVE_ASSERT(class_java_lang_String->loaded);
993 RESOLVE_ASSERT(class_java_lang_String->linked);
994 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
997 TYPEINFO_INIT_NULLTYPE(tinfo);
999 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1000 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
1004 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1011 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
1013 stackelement *stack)
1015 unresolved_method *ref;
1016 constant_FMIref *methodref;
1017 stackelement *instanceslot = NULL;
1018 stackelement *param;
1024 methodref = (constant_FMIref *) iptr[0].val.a;
1025 RESOLVE_ASSERT(methodref);
1026 md = methodref->parseddesc.md;
1029 #ifdef RESOLVE_VERBOSE
1030 fprintf(stderr,"create_unresolved_method\n");
1031 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1032 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1033 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1034 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1035 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1036 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1037 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1040 ref = NEW(unresolved_method);
1042 ref->referermethod = refmethod;
1043 ref->methodref = methodref;
1044 ref->paramconstraints = NULL;
1046 switch (iptr[0].opc) {
1047 case ICMD_INVOKESTATIC:
1048 ref->flags |= RESOLVE_STATIC;
1050 case ICMD_INVOKEVIRTUAL:
1051 case ICMD_INVOKESPECIAL:
1052 case ICMD_INVOKEINTERFACE:
1055 RESOLVE_ASSERT(false);
1058 if (stack && (ref->flags & RESOLVE_STATIC) == 0) {
1059 /* find the instance slot under all the parameter slots on the stack */
1060 instanceslot = stack;
1061 for (i=0; i<md->paramcount; ++i)
1062 instanceslot = instanceslot->prev;
1065 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1067 /* record subtype constraints for the instance type, if any */
1071 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
1073 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
1074 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1075 { /* XXX clean up */
1076 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1077 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
1078 : refmethod->class; /* XXX classrefs */
1079 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
1080 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1084 tip = &(instanceslot->typeinfo);
1086 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1087 &(ref->instancetypes),tip,methodref->classref))
1091 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1094 /* record subtype constraints for the parameter types, if any */
1097 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
1098 type = md->paramtypes[i].type;
1100 RESOLVE_ASSERT(param);
1101 RESOLVE_ASSERT(type == param->type);
1103 if (type == TYPE_ADR) {
1104 if (!ref->paramconstraints) {
1105 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1106 for (j=md->paramcount-1; j>i; --j)
1107 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1109 RESOLVE_ASSERT(ref->paramconstraints);
1110 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1111 ref->paramconstraints + i,&(param->typeinfo),
1112 md->paramtypes[i].classref))
1116 if (ref->paramconstraints)
1117 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1125 /******************************************************************************/
1126 /* FREEING MEMORY */
1127 /******************************************************************************/
1130 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1133 classref_or_classinfo *p = list;
1135 /* this is silly. we *only* need to count the elements for MFREE */
1138 MFREE(list,classref_or_classinfo,(p - list));
1142 /* unresolved_class_free *******************************************************
1144 Free the memory used by an unresolved_class
1147 ref..............the unresolved_class
1149 *******************************************************************************/
1152 unresolved_class_free(unresolved_class *ref)
1154 RESOLVE_ASSERT(ref);
1156 unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
1157 FREE(ref,unresolved_class);
1160 /* unresolved_field_free *******************************************************
1162 Free the memory used by an unresolved_field
1165 ref..............the unresolved_field
1167 *******************************************************************************/
1170 unresolved_field_free(unresolved_field *ref)
1172 RESOLVE_ASSERT(ref);
1174 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1175 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1176 FREE(ref,unresolved_field);
1179 /* unresolved_method_free ******************************************************
1181 Free the memory used by an unresolved_method
1184 ref..............the unresolved_method
1186 *******************************************************************************/
1189 unresolved_method_free(unresolved_method *ref)
1191 RESOLVE_ASSERT(ref);
1193 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1194 if (ref->paramconstraints) {
1196 int count = ref->methodref->parseddesc.md->paramcount;
1198 for (i=0; i<count; ++i)
1199 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1200 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1202 FREE(ref,unresolved_method);
1205 /******************************************************************************/
1207 /******************************************************************************/
1209 /* unresolved_subtype_set_debug_dump *******************************************
1211 Print debug info for unresolved_subtype_set to stream
1214 stset............the unresolved_subtype_set
1215 file.............the stream
1217 *******************************************************************************/
1220 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1222 classref_or_classinfo *p;
1224 if (SUBTYPESET_IS_EMPTY(*stset)) {
1225 fprintf(file," (empty)\n");
1228 p = stset->subtyperefs;
1229 for (;p->any; ++p) {
1230 if (IS_CLASSREF(*p)) {
1231 fprintf(file," ref: ");
1232 utf_fprint(file,p->ref->name);
1235 fprintf(file," cls: ");
1236 utf_fprint(file,p->cls->name);
1243 /* unresolved_class_debug_dump *************************************************
1245 Print debug info for unresolved_class to stream
1248 ref..............the unresolved_class
1249 file.............the stream
1251 *******************************************************************************/
1254 unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
1256 fprintf(file,"unresolved_class(%p):\n",(void *)ref);
1258 fprintf(file," referer : ");
1259 utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
1260 fprintf(file," refmethod : ");
1261 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1262 fprintf(file," refmethodd : ");
1263 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1264 fprintf(file," classname : ");
1265 utf_fprint(file,ref->classref->name); fputc('\n',file);
1266 fprintf(file," subtypeconstraints:\n");
1267 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
1271 /* unresolved_field_debug_dump *************************************************
1273 Print debug info for unresolved_field to stream
1276 ref..............the unresolved_field
1277 file.............the stream
1279 *******************************************************************************/
1282 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1284 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1286 fprintf(file," referer : ");
1287 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1288 fprintf(file," refmethod : ");
1289 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1290 fprintf(file," refmethodd : ");
1291 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1292 fprintf(file," classname : ");
1293 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1294 fprintf(file," name : ");
1295 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1296 fprintf(file," descriptor: ");
1297 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1298 fprintf(file," parseddesc: ");
1299 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1300 fprintf(file," flags : %04x\n",ref->flags);
1301 fprintf(file," instancetypes:\n");
1302 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1303 fprintf(file," valueconstraints:\n");
1304 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1308 /* unresolved_method_debug_dump ************************************************
1310 Print debug info for unresolved_method to stream
1313 ref..............the unresolved_method
1314 file.............the stream
1316 *******************************************************************************/
1319 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1323 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1325 fprintf(file," referer : ");
1326 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1327 fprintf(file," refmethod : ");
1328 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1329 fprintf(file," refmethodd : ");
1330 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1331 fprintf(file," classname : ");
1332 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1333 fprintf(file," name : ");
1334 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1335 fprintf(file," descriptor: ");
1336 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1337 fprintf(file," parseddesc: ");
1338 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1339 fprintf(file," flags : %04x\n",ref->flags);
1340 fprintf(file," instancetypes:\n");
1341 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1342 fprintf(file," paramconstraints:\n");
1343 if (ref->paramconstraints) {
1344 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1345 fprintf(file," param %d:\n",i);
1346 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1350 fprintf(file," (empty)\n");
1356 * These are local overrides for various environment variables in Emacs.
1357 * Please do not remove this and leave it at the end of the file, where
1358 * Emacs will automagically detect them.
1359 * ---------------------------------------------------------------------
1362 * indent-tabs-mode: t
1366 * vim:noexpandtab:sw=4:ts=4: