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 2217 2005-04-05 10:26:33Z 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? */
657 /* { the method reference has been resolved } */
658 declarer = mi->class;
659 RESOLVE_ASSERT(declarer);
662 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
663 /* a static method is accessed via an instance, or vice versa */
664 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
665 (mi->flags & ACC_STATIC) ? "static method called via instance"
666 : "instance method called without instance");
667 return false; /* exception */
670 /* for non-static methods we have to check the constraints on the instance type */
671 if ((ref->flags & RESOLVE_STATIC) == 0) {
672 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
673 &(ref->instancetypes),
674 CLASSREF_OR_CLASSINFO(container),
677 resolveLinkageError,&checked))
679 return false; /* exception */
682 return true; /* be lazy */
689 /* check subtype constraints for TYPE_ADR parameters */
690 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
691 paramtypes = ref->methodref->parseddesc.md->paramtypes;
693 for (i=0; i<(mi->paramcount-instancecount); ++i) {
694 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
695 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
696 if (ref->paramconstraints) {
697 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
698 ref->paramconstraints + i,
699 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
702 resolveLinkageError,&checked))
704 return false; /* exception */
707 return true; /* be lazy */
712 /* check access rights */
713 if (!is_accessible_member(referer,declarer,mi->flags)) {
714 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
715 "method is not accessible XXX add message");
716 return false; /* exception */
719 /* check protected access */
720 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
721 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
722 &(ref->instancetypes),
723 CLASSREF_OR_CLASSINFO(referer),
726 resolveIllegalAccessError,&checked))
728 return false; /* exception */
731 return true; /* be lazy */
734 /* impose loading constraints on parameters (including instance) */
735 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
736 for (i=0; i<mi->paramcount; ++i) {
737 if (mi->paramtypes[i] == TYPE_ADR) {
740 if (i < instancecount)
741 name = container->name; /* XXX should this be declarer->name? */
743 name = paramtypes[i].classref->name;
745 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
746 return false; /* exception */
750 /* impose loading constraing onto return type */
751 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
752 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
753 ref->methodref->parseddesc.md->returntype.classref->name))
754 return false; /* exception */
762 /******************************************************************************/
763 /* CREATING THE DATA STRUCTURES */
764 /******************************************************************************/
767 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
768 unresolved_subtype_set *stset,typeinfo *tinfo,
769 constant_classref *declaredtype)
774 RESOLVE_ASSERT(stset);
775 RESOLVE_ASSERT(tinfo);
777 #ifdef RESOLVE_VERBOSE
778 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
779 #ifdef TYPEINFO_DEBUG
780 /*typeinfo_print(stderr,tinfo,4);*/
781 fprintf(stderr,"\n");
783 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
784 fprintf(stderr,"\n");
787 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
788 *exceptionptr = new_verifyerror(refmethod,
789 "Invalid use of returnAddress");
793 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
794 *exceptionptr = new_verifyerror(refmethod,
795 "Invalid use of uninitialized object");
799 /* the nulltype is always assignable (XXX for reversed?) */
800 if (TYPEINFO_IS_NULLTYPE(*tinfo))
803 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
804 if (declaredtype->name == utf_java_lang_Object
805 && referer->classloader == NULL)
811 count = tinfo->merged->count;
812 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
813 for (i=0; i<count; ++i) {
814 stset->subtyperefs[i] = tinfo->merged->list[i];
816 stset->subtyperefs[count].any = NULL; /* terminate */
819 if ((IS_CLASSREF(tinfo->typeclass)
820 ? tinfo->typeclass.ref->name
821 : tinfo->typeclass.cls->name) == declaredtype->name)
826 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
827 stset->subtyperefs[0] = tinfo->typeclass;
828 stset->subtyperefs[1].any = NULL; /* terminate */
835 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
840 create_unresolved_class(methodinfo *refmethod,
841 constant_classref *classref,
844 unresolved_class *ref;
848 #ifdef RESOLVE_VERBOSE
849 fprintf(stderr,"create_unresolved_class\n");
850 fprintf(stderr," referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
851 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
852 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
853 fprintf(stderr," name : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
856 ref = NEW(unresolved_class);
857 ref->classref = classref;
858 ref->referermethod = refmethod;
861 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
862 &(ref->subtypeconstraints),valuetype,classref))
866 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
873 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
877 unresolved_field *ref;
878 constant_FMIref *fieldref = NULL;
879 stackelement *instanceslot = NULL;
882 typeinfo *tip = NULL;
885 #ifdef RESOLVE_VERBOSE
886 fprintf(stderr,"create_unresolved_field\n");
887 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
888 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
889 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
892 ref = NEW(unresolved_field);
894 ref->referermethod = refmethod;
896 switch (iptr[0].opc) {
898 ref->flags |= RESOLVE_PUTFIELD;
900 instanceslot = stack->prev;
901 tip = &(stack->typeinfo);
903 fieldref = (constant_FMIref *) iptr[0].val.a;
906 case ICMD_PUTFIELDCONST:
907 ref->flags |= RESOLVE_PUTFIELD;
908 if (stack) instanceslot = stack;
909 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
913 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
914 fieldref = (constant_FMIref *) iptr[0].val.a;
915 if (stack) tip = &(stack->typeinfo);
918 case ICMD_PUTSTATICCONST:
919 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
920 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
924 if (stack) instanceslot = stack;
925 fieldref = (constant_FMIref *) iptr[0].val.a;
929 ref->flags |= RESOLVE_STATIC;
930 fieldref = (constant_FMIref *) iptr[0].val.a;
934 RESOLVE_ASSERT(fieldref);
935 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
936 fd = fieldref->parseddesc.fd;
939 #ifdef RESOLVE_VERBOSE
940 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
941 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
942 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
943 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
945 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
948 ref->fieldref = fieldref;
950 /* record subtype constraints for the instance type, if any */
953 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
955 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
956 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
958 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
959 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
960 : refmethod->class; /* XXX classrefs */
961 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
962 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
966 insttip = &(instanceslot->typeinfo);
968 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
969 &(ref->instancetypes),insttip,fieldref->classref))
973 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
976 /* record subtype constraints for the value type, if any */
978 if (stack && type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
980 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
982 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
983 RESOLVE_ASSERT(class_java_lang_String);
984 RESOLVE_ASSERT(class_java_lang_String->loaded);
985 RESOLVE_ASSERT(class_java_lang_String->linked);
986 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
989 TYPEINFO_INIT_NULLTYPE(tinfo);
991 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
992 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
996 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1003 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
1005 stackelement *stack)
1007 unresolved_method *ref;
1008 constant_FMIref *methodref;
1009 stackelement *instanceslot = NULL;
1010 stackelement *param;
1016 methodref = (constant_FMIref *) iptr[0].val.a;
1017 RESOLVE_ASSERT(methodref);
1018 md = methodref->parseddesc.md;
1021 #ifdef RESOLVE_VERBOSE
1022 fprintf(stderr,"create_unresolved_method\n");
1023 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1024 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1025 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1026 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1027 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1028 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1029 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1032 ref = NEW(unresolved_method);
1034 ref->referermethod = refmethod;
1035 ref->methodref = methodref;
1036 ref->paramconstraints = NULL;
1038 switch (iptr[0].opc) {
1039 case ICMD_INVOKESTATIC:
1040 ref->flags |= RESOLVE_STATIC;
1042 case ICMD_INVOKEVIRTUAL:
1043 case ICMD_INVOKESPECIAL:
1044 case ICMD_INVOKEINTERFACE:
1047 RESOLVE_ASSERT(false);
1050 if (stack && (ref->flags & RESOLVE_STATIC) == 0) {
1051 /* find the instance slot under all the parameter slots on the stack */
1052 instanceslot = stack;
1053 for (i=0; i<md->paramcount; ++i)
1054 instanceslot = instanceslot->prev;
1057 RESOLVE_ASSERT(!stack || instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1059 /* record subtype constraints for the instance type, if any */
1063 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
1065 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
1066 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1067 { /* XXX clean up */
1068 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1069 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
1070 : refmethod->class; /* XXX classrefs */
1071 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
1072 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1076 tip = &(instanceslot->typeinfo);
1078 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1079 &(ref->instancetypes),tip,methodref->classref))
1083 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1086 /* record subtype constraints for the parameter types, if any */
1089 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
1090 type = md->paramtypes[i].type;
1092 RESOLVE_ASSERT(param);
1093 RESOLVE_ASSERT(type == param->type);
1095 if (type == TYPE_ADR) {
1096 if (!ref->paramconstraints) {
1097 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1098 for (j=md->paramcount-1; j>i; --j)
1099 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1101 RESOLVE_ASSERT(ref->paramconstraints);
1102 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1103 ref->paramconstraints + i,&(param->typeinfo),
1104 md->paramtypes[i].classref))
1108 if (ref->paramconstraints)
1109 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1117 /******************************************************************************/
1118 /* FREEING MEMORY */
1119 /******************************************************************************/
1122 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1125 classref_or_classinfo *p = list;
1127 /* this is silly. we *only* need to count the elements for MFREE */
1130 MFREE(list,classref_or_classinfo,(p - list));
1134 /* unresolved_class_free *******************************************************
1136 Free the memory used by an unresolved_class
1139 ref..............the unresolved_class
1141 *******************************************************************************/
1144 unresolved_class_free(unresolved_class *ref)
1146 RESOLVE_ASSERT(ref);
1148 unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
1149 FREE(ref,unresolved_class);
1152 /* unresolved_field_free *******************************************************
1154 Free the memory used by an unresolved_field
1157 ref..............the unresolved_field
1159 *******************************************************************************/
1162 unresolved_field_free(unresolved_field *ref)
1164 RESOLVE_ASSERT(ref);
1166 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1167 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1168 FREE(ref,unresolved_field);
1171 /* unresolved_method_free ******************************************************
1173 Free the memory used by an unresolved_method
1176 ref..............the unresolved_method
1178 *******************************************************************************/
1181 unresolved_method_free(unresolved_method *ref)
1183 RESOLVE_ASSERT(ref);
1185 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1186 if (ref->paramconstraints) {
1188 int count = ref->methodref->parseddesc.md->paramcount;
1190 for (i=0; i<count; ++i)
1191 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1192 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1194 FREE(ref,unresolved_method);
1197 /******************************************************************************/
1199 /******************************************************************************/
1201 /* unresolved_subtype_set_debug_dump *******************************************
1203 Print debug info for unresolved_subtype_set to stream
1206 stset............the unresolved_subtype_set
1207 file.............the stream
1209 *******************************************************************************/
1212 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1214 classref_or_classinfo *p;
1216 if (SUBTYPESET_IS_EMPTY(*stset)) {
1217 fprintf(file," (empty)\n");
1220 p = stset->subtyperefs;
1221 for (;p->any; ++p) {
1222 if (IS_CLASSREF(*p)) {
1223 fprintf(file," ref: ");
1224 utf_fprint(file,p->ref->name);
1227 fprintf(file," cls: ");
1228 utf_fprint(file,p->cls->name);
1235 /* unresolved_class_debug_dump *************************************************
1237 Print debug info for unresolved_class to stream
1240 ref..............the unresolved_class
1241 file.............the stream
1243 *******************************************************************************/
1246 unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
1248 fprintf(file,"unresolved_class(%p):\n",(void *)ref);
1250 fprintf(file," referer : ");
1251 utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
1252 fprintf(file," refmethod : ");
1253 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1254 fprintf(file," refmethodd : ");
1255 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1256 fprintf(file," classname : ");
1257 utf_fprint(file,ref->classref->name); fputc('\n',file);
1258 fprintf(file," subtypeconstraints:\n");
1259 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
1263 /* unresolved_field_debug_dump *************************************************
1265 Print debug info for unresolved_field to stream
1268 ref..............the unresolved_field
1269 file.............the stream
1271 *******************************************************************************/
1274 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1276 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1278 fprintf(file," referer : ");
1279 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1280 fprintf(file," refmethod : ");
1281 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1282 fprintf(file," refmethodd : ");
1283 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1284 fprintf(file," classname : ");
1285 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1286 fprintf(file," name : ");
1287 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1288 fprintf(file," descriptor: ");
1289 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1290 fprintf(file," parseddesc: ");
1291 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1292 fprintf(file," flags : %04x\n",ref->flags);
1293 fprintf(file," instancetypes:\n");
1294 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1295 fprintf(file," valueconstraints:\n");
1296 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1300 /* unresolved_method_debug_dump ************************************************
1302 Print debug info for unresolved_method to stream
1305 ref..............the unresolved_method
1306 file.............the stream
1308 *******************************************************************************/
1311 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1315 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1317 fprintf(file," referer : ");
1318 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1319 fprintf(file," refmethod : ");
1320 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1321 fprintf(file," refmethodd : ");
1322 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1323 fprintf(file," classname : ");
1324 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1325 fprintf(file," name : ");
1326 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1327 fprintf(file," descriptor: ");
1328 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1329 fprintf(file," parseddesc: ");
1330 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1331 fprintf(file," flags : %04x\n",ref->flags);
1332 fprintf(file," instancetypes:\n");
1333 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1334 fprintf(file," paramconstraints:\n");
1335 if (ref->paramconstraints) {
1336 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1337 fprintf(file," param %d:\n",i);
1338 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1342 fprintf(file," (empty)\n");
1348 * These are local overrides for various environment variables in Emacs.
1349 * Please do not remove this and leave it at the end of the file, where
1350 * Emacs will automagically detect them.
1351 * ---------------------------------------------------------------------
1354 * indent-tabs-mode: t
1358 * vim:noexpandtab:sw=4:ts=4: