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
29 Changes: Christan Thalinger
31 $Id: resolve.c 2572 2005-06-06 15:36:12Z twisti $
38 #include "mm/memory.h"
39 #include "vm/resolve.h"
40 #include "vm/access.h"
41 #include "vm/classcache.h"
42 #include "vm/descriptor.h"
43 #include "vm/exceptions.h"
44 #include "vm/linker.h"
45 #include "vm/loader.h"
46 #include "vm/stringlocal.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, resolve_mode_t mode, methodinfo **result)
614 classinfo *container;
617 typedesc *paramtypes;
623 RESOLVE_ASSERT(result);
624 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
626 #ifdef RESOLVE_VERBOSE
627 unresolved_method_debug_dump(ref,stderr);
632 /* the class containing the reference */
633 referer = ref->methodref->classref->referer;
634 RESOLVE_ASSERT(referer);
636 /* first we must resolve the class containg the method */
637 if (!resolve_class_from_name(referer,ref->referermethod,
638 ref->methodref->classref->name,mode,true,&container))
640 /* the class reference could not be resolved */
641 return false; /* exception */
644 return true; /* be lazy */
646 RESOLVE_ASSERT(container);
648 /* now we must find the declaration of the method in `container`
649 * or one of its superclasses */
651 if (container->flags & ACC_INTERFACE) {
652 mi = class_resolveinterfacemethod(container,
653 ref->methodref->name,
654 ref->methodref->descriptor,
658 mi = class_resolveclassmethod(container,
659 ref->methodref->name,
660 ref->methodref->descriptor,
665 return false; /* exception */ /* XXX set exceptionptr? */
667 /* { the method reference has been resolved } */
669 declarer = mi->class;
670 RESOLVE_ASSERT(declarer);
674 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) { /* a static method is accessed via an instance, or vice versa */
676 new_exception_message(string_java_lang_IncompatibleClassChangeError,
677 (mi->flags & ACC_STATIC) ? "static method called via instance"
678 : "instance method called without instance");
682 /* have the method params already been parsed? no, do it. */
684 if (!mi->parseddesc->params)
685 if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
688 /* for non-static methods we have to check the constraints on the */
691 if (!(ref->flags & RESOLVE_STATIC)) {
692 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
693 &(ref->instancetypes),
694 CLASSREF_OR_CLASSINFO(container),
697 resolveLinkageError,&checked))
699 return false; /* exception */
702 return true; /* be lazy */
709 /* check subtype constraints for TYPE_ADR parameters */
711 RESOLVE_ASSERT(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
712 paramtypes = mi->parseddesc->paramtypes;
714 for (i = 0; i < mi->parseddesc->paramcount; i++) {
715 if (paramtypes[i].type == TYPE_ADR) {
716 if (ref->paramconstraints) {
717 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
718 ref->paramconstraints + i,
719 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
722 resolveLinkageError,&checked))
724 return false; /* exception */
727 return true; /* be lazy */
732 /* check access rights */
734 if (!is_accessible_member(referer,declarer,mi->flags)) {
735 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
736 "method is not accessible XXX add message");
737 return false; /* exception */
740 /* check protected access */
742 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
743 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
744 &(ref->instancetypes),
745 CLASSREF_OR_CLASSINFO(referer),
748 resolveIllegalAccessError,&checked))
750 return false; /* exception */
753 return true; /* be lazy */
756 /* impose loading constraints on parameters (including instance) */
758 paramtypes = mi->parseddesc->paramtypes;
760 for (i = 0; i < mi->parseddesc->paramcount; i++) {
761 if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
764 if (i < instancecount)
765 name = container->name; /* XXX should this be declarer->name? */
767 name = paramtypes[i].classref->name;
769 if (!classcache_add_constraint(referer->classloader,
770 declarer->classloader, name))
771 return false; /* exception */
775 /* impose loading constraing onto return type */
777 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
778 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
779 ref->methodref->parseddesc.md->returntype.classref->name))
780 return false; /* exception */
788 /******************************************************************************/
789 /* CREATING THE DATA STRUCTURES */
790 /******************************************************************************/
793 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
794 unresolved_subtype_set *stset,typeinfo *tinfo,
795 constant_classref *declaredtype)
800 RESOLVE_ASSERT(stset);
801 RESOLVE_ASSERT(tinfo);
803 #ifdef RESOLVE_VERBOSE
804 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
805 #ifdef TYPEINFO_DEBUG
806 /*typeinfo_print(stderr,tinfo,4);*/
807 fprintf(stderr,"\n");
809 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
810 fprintf(stderr,"\n");
813 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
814 *exceptionptr = new_verifyerror(refmethod,
815 "Invalid use of returnAddress");
819 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
820 *exceptionptr = new_verifyerror(refmethod,
821 "Invalid use of uninitialized object");
825 /* the nulltype is always assignable (XXX for reversed?) */
826 if (TYPEINFO_IS_NULLTYPE(*tinfo))
829 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
830 if (declaredtype->name == utf_java_lang_Object
831 && referer->classloader == NULL)
837 count = tinfo->merged->count;
838 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
839 for (i=0; i<count; ++i) {
840 stset->subtyperefs[i] = tinfo->merged->list[i];
842 stset->subtyperefs[count].any = NULL; /* terminate */
845 if ((IS_CLASSREF(tinfo->typeclass)
846 ? tinfo->typeclass.ref->name
847 : tinfo->typeclass.cls->name) == declaredtype->name)
852 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
853 stset->subtyperefs[0] = tinfo->typeclass;
854 stset->subtyperefs[1].any = NULL; /* terminate */
861 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
866 create_unresolved_class(methodinfo *refmethod,
867 constant_classref *classref,
870 unresolved_class *ref;
874 #ifdef RESOLVE_VERBOSE
875 fprintf(stderr,"create_unresolved_class\n");
876 fprintf(stderr," referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
878 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
879 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
881 fprintf(stderr," name : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
884 ref = NEW(unresolved_class);
885 ref->classref = classref;
886 ref->referermethod = refmethod;
889 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
890 &(ref->subtypeconstraints),valuetype,classref))
894 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
902 create_unresolved_field(classinfo *referer, methodinfo *refmethod,
906 unresolved_field *ref;
907 constant_FMIref *fieldref = NULL;
908 stackelement *instanceslot = NULL;
911 typeinfo *tip = NULL;
914 #ifdef RESOLVE_VERBOSE
915 fprintf(stderr,"create_unresolved_field\n");
916 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
917 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
918 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
921 ref = NEW(unresolved_field);
923 ref->referermethod = refmethod;
925 switch (iptr[0].opc) {
927 ref->flags |= RESOLVE_PUTFIELD;
929 instanceslot = stack->prev;
930 tip = &(stack->typeinfo);
932 fieldref = (constant_FMIref *) iptr[0].val.a;
935 case ICMD_PUTFIELDCONST:
936 ref->flags |= RESOLVE_PUTFIELD;
937 if (stack) instanceslot = stack;
938 fieldref = (constant_FMIref *) iptr[1].val.a;
942 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
943 fieldref = (constant_FMIref *) iptr[0].val.a;
944 if (stack) tip = &(stack->typeinfo);
947 case ICMD_PUTSTATICCONST:
948 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
949 fieldref = (constant_FMIref *) iptr[1].val.a;
953 if (stack) instanceslot = stack;
954 fieldref = (constant_FMIref *) iptr[0].val.a;
958 ref->flags |= RESOLVE_STATIC;
959 fieldref = (constant_FMIref *) iptr[0].val.a;
963 RESOLVE_ASSERT(fieldref);
964 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
965 fd = fieldref->parseddesc.fd;
968 #ifdef RESOLVE_VERBOSE
969 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
970 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
971 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
972 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
974 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
977 ref->fieldref = fieldref;
979 /* record subtype constraints for the instance type, if any */
982 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
984 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
985 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
987 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
988 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
989 : refmethod->class; /* XXX classrefs */
990 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
991 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
995 insttip = &(instanceslot->typeinfo);
997 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
998 &(ref->instancetypes),insttip,fieldref->classref))
1002 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1005 /* record subtype constraints for the value type, if any */
1007 if (stack && type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
1009 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
1011 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
1012 RESOLVE_ASSERT(class_java_lang_String);
1013 RESOLVE_ASSERT(class_java_lang_String->loaded);
1014 RESOLVE_ASSERT(class_java_lang_String->linked);
1015 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
1018 TYPEINFO_INIT_NULLTYPE(tinfo);
1020 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1021 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
1025 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1032 create_unresolved_method(classinfo *referer, methodinfo *refmethod,
1034 stackelement *stack)
1036 unresolved_method *ref;
1037 constant_FMIref *methodref;
1038 stackelement *instanceslot = NULL;
1039 stackelement *param;
1045 methodref = (constant_FMIref *) iptr[0].val.a;
1046 RESOLVE_ASSERT(methodref);
1047 md = methodref->parseddesc.md;
1050 #ifdef RESOLVE_VERBOSE
1051 fprintf(stderr,"create_unresolved_method\n");
1052 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1053 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1054 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1055 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1056 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1057 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1058 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1061 ref = NEW(unresolved_method);
1063 ref->referermethod = refmethod;
1064 ref->methodref = methodref;
1065 ref->paramconstraints = NULL;
1067 switch (iptr[0].opc) {
1068 case ICMD_INVOKESTATIC:
1069 ref->flags |= RESOLVE_STATIC;
1071 case ICMD_INVOKEVIRTUAL:
1072 case ICMD_INVOKESPECIAL:
1073 case ICMD_INVOKEINTERFACE:
1076 RESOLVE_ASSERT(false);
1079 if (stack && (ref->flags & RESOLVE_STATIC) == 0) {
1080 /* find the instance slot under all the parameter slots on the stack */
1081 instanceslot = stack;
1082 for (i=0; i<md->paramcount; ++i)
1083 instanceslot = instanceslot->prev;
1086 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1088 /* record subtype constraints for the instance type, if any */
1092 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
1094 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
1095 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1096 { /* XXX clean up */
1097 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1098 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
1099 : refmethod->class; /* XXX classrefs */
1100 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
1101 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1105 tip = &(instanceslot->typeinfo);
1107 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1108 &(ref->instancetypes),tip,methodref->classref))
1112 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1115 /* record subtype constraints for the parameter types, if any */
1118 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
1119 type = md->paramtypes[i].type;
1121 RESOLVE_ASSERT(param);
1122 RESOLVE_ASSERT(type == param->type);
1124 if (type == TYPE_ADR) {
1125 if (!ref->paramconstraints) {
1126 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1127 for (j=md->paramcount-1; j>i; --j)
1128 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1130 RESOLVE_ASSERT(ref->paramconstraints);
1131 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1132 ref->paramconstraints + i,&(param->typeinfo),
1133 md->paramtypes[i].classref))
1137 if (ref->paramconstraints)
1138 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1146 /******************************************************************************/
1147 /* FREEING MEMORY */
1148 /******************************************************************************/
1151 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1154 classref_or_classinfo *p = list;
1156 /* this is silly. we *only* need to count the elements for MFREE */
1159 MFREE(list,classref_or_classinfo,(p - list));
1163 /* unresolved_class_free *******************************************************
1165 Free the memory used by an unresolved_class
1168 ref..............the unresolved_class
1170 *******************************************************************************/
1173 unresolved_class_free(unresolved_class *ref)
1175 RESOLVE_ASSERT(ref);
1177 unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
1178 FREE(ref,unresolved_class);
1181 /* unresolved_field_free *******************************************************
1183 Free the memory used by an unresolved_field
1186 ref..............the unresolved_field
1188 *******************************************************************************/
1191 unresolved_field_free(unresolved_field *ref)
1193 RESOLVE_ASSERT(ref);
1195 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1196 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1197 FREE(ref,unresolved_field);
1200 /* unresolved_method_free ******************************************************
1202 Free the memory used by an unresolved_method
1205 ref..............the unresolved_method
1207 *******************************************************************************/
1210 unresolved_method_free(unresolved_method *ref)
1212 RESOLVE_ASSERT(ref);
1214 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1215 if (ref->paramconstraints) {
1217 int count = ref->methodref->parseddesc.md->paramcount;
1219 for (i=0; i<count; ++i)
1220 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1221 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1223 FREE(ref,unresolved_method);
1226 /******************************************************************************/
1228 /******************************************************************************/
1230 /* unresolved_subtype_set_debug_dump *******************************************
1232 Print debug info for unresolved_subtype_set to stream
1235 stset............the unresolved_subtype_set
1236 file.............the stream
1238 *******************************************************************************/
1241 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1243 classref_or_classinfo *p;
1245 if (SUBTYPESET_IS_EMPTY(*stset)) {
1246 fprintf(file," (empty)\n");
1249 p = stset->subtyperefs;
1250 for (;p->any; ++p) {
1251 if (IS_CLASSREF(*p)) {
1252 fprintf(file," ref: ");
1253 utf_fprint(file,p->ref->name);
1256 fprintf(file," cls: ");
1257 utf_fprint(file,p->cls->name);
1264 /* unresolved_class_debug_dump *************************************************
1266 Print debug info for unresolved_class to stream
1269 ref..............the unresolved_class
1270 file.............the stream
1272 *******************************************************************************/
1275 unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
1277 fprintf(file,"unresolved_class(%p):\n",(void *)ref);
1279 fprintf(file," referer : ");
1280 utf_fprint(file,ref->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->classref->name); fputc('\n',file);
1287 fprintf(file," subtypeconstraints:\n");
1288 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
1292 /* unresolved_field_debug_dump *************************************************
1294 Print debug info for unresolved_field to stream
1297 ref..............the unresolved_field
1298 file.............the stream
1300 *******************************************************************************/
1303 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1305 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1307 fprintf(file," referer : ");
1308 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1309 fprintf(file," refmethod : ");
1310 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1311 fprintf(file," refmethodd : ");
1312 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1313 fprintf(file," classname : ");
1314 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1315 fprintf(file," name : ");
1316 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1317 fprintf(file," descriptor: ");
1318 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1319 fprintf(file," parseddesc: ");
1320 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1321 fprintf(file," flags : %04x\n",ref->flags);
1322 fprintf(file," instancetypes:\n");
1323 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1324 fprintf(file," valueconstraints:\n");
1325 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1329 /* unresolved_method_debug_dump ************************************************
1331 Print debug info for unresolved_method to stream
1334 ref..............the unresolved_method
1335 file.............the stream
1337 *******************************************************************************/
1340 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1344 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1346 fprintf(file," referer : ");
1347 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1348 fprintf(file," refmethod : ");
1349 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1350 fprintf(file," refmethodd : ");
1351 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1352 fprintf(file," classname : ");
1353 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1354 fprintf(file," name : ");
1355 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1356 fprintf(file," descriptor: ");
1357 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1358 fprintf(file," parseddesc: ");
1359 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1360 fprintf(file," flags : %04x\n",ref->flags);
1361 fprintf(file," instancetypes:\n");
1362 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1363 fprintf(file," paramconstraints:\n");
1364 if (ref->paramconstraints) {
1365 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1366 fprintf(file," param %d:\n",i);
1367 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1371 fprintf(file," (empty)\n");
1377 * These are local overrides for various environment variables in Emacs.
1378 * Please do not remove this and leave it at the end of the file, where
1379 * Emacs will automagically detect them.
1380 * ---------------------------------------------------------------------
1383 * indent-tabs-mode: t
1387 * vim:noexpandtab:sw=4:ts=4: