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 2195 2005-04-03 16:53:16Z 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(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(");
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(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(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 /* FIELD RESOLUTION */
394 /******************************************************************************/
396 /* for documentation see resolve.h */
398 resolve_field(unresolved_field *ref,
403 classinfo *container;
405 constant_classref *fieldtyperef;
410 RESOLVE_ASSERT(result);
411 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
415 #ifdef RESOLVE_VERBOSE
416 unresolved_field_debug_dump(ref,stderr);
419 /* the class containing the reference */
420 referer = ref->fieldref->classref->referer;
421 RESOLVE_ASSERT(referer);
423 /* first we must resolve the class containg the field */
424 if (!resolve_class(referer,ref->referermethod,
425 ref->fieldref->classref->name,mode,&container))
427 /* the class reference could not be resolved */
428 return false; /* exception */
431 return true; /* be lazy */
433 RESOLVE_ASSERT(container);
434 RESOLVE_ASSERT(container->loaded && container->linked);
436 /* now we must find the declaration of the field in `container`
437 * or one of its superclasses */
439 #ifdef RESOLVE_VERBOSE
440 fprintf(stderr," resolving field in class...\n");
443 fi = class_resolvefield(container,
444 ref->fieldref->name,ref->fieldref->descriptor,
447 return false; /* exception */
449 /* { the field reference has been resolved } */
450 declarer = fi->class;
451 RESOLVE_ASSERT(declarer);
452 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
454 #ifdef RESOLVE_VERBOSE
455 fprintf(stderr," checking static...\n");
459 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
460 /* a static field is accessed via an instance, or vice versa */
461 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
462 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
463 : "instance field accessed without instance");
464 return false; /* exception */
467 /* for non-static accesses we have to check the constraints on the instance type */
468 if ((ref->flags & RESOLVE_STATIC) == 0) {
469 #ifdef RESOLVE_VERBOSE
470 fprintf(stderr," checking instance types...\n");
473 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
474 &(ref->instancetypes),
475 CLASSREF_OR_CLASSINFO(container),
478 resolveLinkageError,&checked))
480 return false; /* exception */
483 return true; /* be lazy */
486 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
488 /* for PUT* instructions we have to check the constraints on the value type */
489 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
490 RESOLVE_ASSERT(fieldtyperef);
491 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
492 /* check subtype constraints */
493 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
494 &(ref->valueconstraints),
495 CLASSREF_OR_CLASSINFO(fieldtyperef),
498 resolveLinkageError,&checked))
500 return false; /* exception */
503 return true; /* be lazy */
507 /* check access rights */
508 if (!is_accessible_member(referer,declarer,fi->flags)) {
509 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
510 "field is not accessible XXX add message");
511 return false; /* exception */
514 /* check protected access */
515 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
516 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
517 &(ref->instancetypes),
518 CLASSREF_OR_CLASSINFO(referer),
521 resolveIllegalAccessError,&checked))
523 return false; /* exception */
526 return true; /* be lazy */
529 /* impose loading constraint on field type */
530 if (fi->type == TYPE_ADR) {
531 RESOLVE_ASSERT(fieldtyperef);
532 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
534 return false; /* exception */
542 /******************************************************************************/
543 /* METHOD RESOLUTION */
544 /******************************************************************************/
546 /* for documentation see resolve.h */
548 resolve_method(unresolved_method *ref,
553 classinfo *container;
556 typedesc *paramtypes;
562 RESOLVE_ASSERT(result);
563 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
565 #ifdef RESOLVE_VERBOSE
566 unresolved_method_debug_dump(ref,stderr);
571 /* the class containing the reference */
572 referer = ref->methodref->classref->referer;
573 RESOLVE_ASSERT(referer);
575 /* first we must resolve the class containg the method */
576 if (!resolve_class(referer,ref->referermethod,
577 ref->methodref->classref->name,mode,&container))
579 /* the class reference could not be resolved */
580 return false; /* exception */
583 return true; /* be lazy */
585 RESOLVE_ASSERT(container);
587 /* now we must find the declaration of the method in `container`
588 * or one of its superclasses */
590 if ((container->flags & ACC_INTERFACE) != 0) {
591 mi = class_resolveinterfacemethod(container,
592 ref->methodref->name,ref->methodref->descriptor,
596 mi = class_resolveclassmethod(container,
597 ref->methodref->name,ref->methodref->descriptor,
601 return false; /* exception */ /* XXX set exceptionptr? */
603 /* { the method reference has been resolved } */
604 declarer = mi->class;
605 RESOLVE_ASSERT(declarer);
608 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
609 /* a static method is accessed via an instance, or vice versa */
610 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
611 (mi->flags & ACC_STATIC) ? "static method called via instance"
612 : "instance method called without instance");
613 return false; /* exception */
616 /* for non-static methods we have to check the constraints on the instance type */
617 if ((ref->flags & RESOLVE_STATIC) == 0) {
618 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
619 &(ref->instancetypes),
620 CLASSREF_OR_CLASSINFO(container),
623 resolveLinkageError,&checked))
625 return false; /* exception */
628 return true; /* be lazy */
635 /* check subtype constraints for TYPE_ADR parameters */
636 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
637 paramtypes = ref->methodref->parseddesc.md->paramtypes;
639 for (i=0; i<(mi->paramcount-instancecount); ++i) {
640 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
641 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
642 if (ref->paramconstraints) {
643 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
644 ref->paramconstraints + i,
645 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
648 resolveLinkageError,&checked))
650 return false; /* exception */
653 return true; /* be lazy */
658 /* check access rights */
659 if (!is_accessible_member(referer,declarer,mi->flags)) {
660 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
661 "method is not accessible XXX add message");
662 return false; /* exception */
665 /* check protected access */
666 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
667 /* XXX do we also need to check (referer subclass_of declarer)? */
668 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
669 &(ref->instancetypes),
670 CLASSREF_OR_CLASSINFO(referer),
673 resolveIllegalAccessError,&checked))
675 return false; /* exception */
678 return true; /* be lazy */
681 /* impose loading constraints on parameters (including instance) */
682 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
683 for (i=0; i<mi->paramcount; ++i) {
684 if (mi->paramtypes[i] == TYPE_ADR) {
687 if (i < instancecount)
688 name = container->name; /* XXX should this be declarer->name? */
690 name = paramtypes[i].classref->name;
692 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
693 return false; /* exception */
697 /* impose loading constraing onto return type */
698 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
699 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
700 ref->methodref->parseddesc.md->returntype.classref->name))
701 return false; /* exception */
709 /******************************************************************************/
710 /* CREATING THE DATA STRUCTURES */
711 /******************************************************************************/
714 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
715 unresolved_subtype_set *stset,typeinfo *tinfo,
716 constant_classref *declaredtype)
721 RESOLVE_ASSERT(stset);
722 RESOLVE_ASSERT(tinfo);
724 #ifdef RESOLVE_VERBOSE
725 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
726 #ifdef TYPEINFO_DEBUG
727 /*typeinfo_print(stderr,tinfo,4);*/
728 fprintf(stderr,"\n");
730 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
731 fprintf(stderr,"\n");
734 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
735 *exceptionptr = new_verifyerror(refmethod,
736 "Invalid use of returnAddress");
740 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
741 *exceptionptr = new_verifyerror(refmethod,
742 "Invalid use of uninitialized object");
746 /* the nulltype is always assignable (XXX for reversed?) */
747 if (TYPEINFO_IS_NULLTYPE(*tinfo))
750 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
751 if (declaredtype->name == utf_java_lang_Object
752 && referer->classloader == NULL)
758 count = tinfo->merged->count;
759 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
760 for (i=0; i<count; ++i) {
761 stset->subtyperefs[i] = tinfo->merged->list[i];
763 stset->subtyperefs[count].any = NULL; /* terminate */
766 if ((IS_CLASSREF(tinfo->typeclass)
767 ? tinfo->typeclass.ref->name
768 : tinfo->typeclass.cls->name) == declaredtype->name)
773 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
774 stset->subtyperefs[0] = tinfo->typeclass;
775 stset->subtyperefs[1].any = NULL; /* terminate */
782 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
787 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
791 unresolved_field *ref;
792 constant_FMIref *fieldref = NULL;
793 stackelement *instanceslot = NULL;
796 typeinfo *tip = NULL;
799 #ifdef RESOLVE_VERBOSE
800 fprintf(stderr,"create_unresolved_field\n");
801 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
802 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
803 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
806 ref = NEW(unresolved_field);
808 ref->referermethod = refmethod;
810 switch (iptr[0].opc) {
812 ref->flags |= RESOLVE_PUTFIELD;
813 instanceslot = stack->prev;
814 tip = &(stack->typeinfo);
815 fieldref = (constant_FMIref *) iptr[0].val.a;
818 case ICMD_PUTFIELDCONST:
819 ref->flags |= RESOLVE_PUTFIELD;
820 instanceslot = stack;
821 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
825 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
826 fieldref = (constant_FMIref *) iptr[0].val.a;
827 tip = &(stack->typeinfo);
830 case ICMD_PUTSTATICCONST:
831 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
832 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
836 instanceslot = stack;
837 fieldref = (constant_FMIref *) iptr[0].val.a;
841 ref->flags |= RESOLVE_STATIC;
842 fieldref = (constant_FMIref *) iptr[0].val.a;
846 RESOLVE_ASSERT(fieldref);
847 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
848 fd = fieldref->parseddesc.fd;
851 #ifdef RESOLVE_VERBOSE
852 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
853 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
854 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
855 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
857 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
860 ref->fieldref = fieldref;
862 /* record subtype constraints for the instance type, if any */
865 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
867 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
868 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
870 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
871 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
872 : refmethod->class; /* XXX classrefs */
873 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
874 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
878 insttip = &(instanceslot->typeinfo);
880 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
881 &(ref->instancetypes),insttip,fieldref->classref))
885 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
888 /* record subtype constraints for the value type, if any */
890 if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
892 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
894 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
895 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
898 TYPEINFO_INIT_NULLTYPE(tinfo);
900 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
901 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
905 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
912 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
916 unresolved_method *ref;
917 constant_FMIref *methodref;
918 stackelement *instanceslot = NULL;
925 methodref = (constant_FMIref *) iptr[0].val.a;
926 RESOLVE_ASSERT(methodref);
927 md = methodref->parseddesc.md;
930 #ifdef RESOLVE_VERBOSE
931 fprintf(stderr,"create_unresolved_method\n");
932 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
933 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
934 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
935 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
936 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
937 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
938 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
941 ref = NEW(unresolved_method);
943 ref->referermethod = refmethod;
944 ref->methodref = methodref;
945 ref->paramconstraints = NULL;
947 switch (iptr[0].opc) {
948 case ICMD_INVOKESTATIC:
949 ref->flags |= RESOLVE_STATIC;
951 case ICMD_INVOKEVIRTUAL:
952 case ICMD_INVOKESPECIAL:
953 case ICMD_INVOKEINTERFACE:
956 RESOLVE_ASSERT(false);
959 if ((ref->flags & RESOLVE_STATIC) == 0) {
960 /* find the instance slot under all the parameter slots on the stack */
961 instanceslot = stack;
962 for (i=0; i<md->paramcount; ++i)
963 instanceslot = instanceslot->prev;
966 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
968 /* record subtype constraints for the instance type, if any */
972 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
974 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
975 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
977 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
978 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
979 : refmethod->class; /* XXX classrefs */
980 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
981 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
985 tip = &(instanceslot->typeinfo);
987 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
988 &(ref->instancetypes),tip,methodref->classref))
992 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
995 /* record subtype constraints for the parameter types, if any */
997 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
998 type = md->paramtypes[i].type;
1000 RESOLVE_ASSERT(param);
1001 RESOLVE_ASSERT(type == param->type);
1003 if (type == TYPE_ADR) {
1004 if (!ref->paramconstraints) {
1005 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1006 for (j=md->paramcount-1; j>i; --j)
1007 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1009 RESOLVE_ASSERT(ref->paramconstraints);
1010 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1011 ref->paramconstraints + i,&(param->typeinfo),
1012 md->paramtypes[i].classref))
1016 if (ref->paramconstraints)
1017 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1024 /******************************************************************************/
1025 /* FREEING MEMORY */
1026 /******************************************************************************/
1029 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1032 classref_or_classinfo *p = list;
1034 /* this is silly. we *only* need to count the elements for MFREE */
1037 MFREE(list,classref_or_classinfo,(p - list));
1041 /* unresolved_field_free *******************************************************
1043 Free the memory used by an unresolved_field
1046 ref..............the unresolved_field
1048 *******************************************************************************/
1051 unresolved_field_free(unresolved_field *ref)
1053 RESOLVE_ASSERT(ref);
1055 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1056 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1057 FREE(ref,unresolved_field);
1060 /* unresolved_method_free ******************************************************
1062 Free the memory used by an unresolved_method
1065 ref..............the unresolved_method
1067 *******************************************************************************/
1070 unresolved_method_free(unresolved_method *ref)
1072 RESOLVE_ASSERT(ref);
1074 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1075 if (ref->paramconstraints) {
1077 int count = ref->methodref->parseddesc.md->paramcount;
1079 for (i=0; i<count; ++i)
1080 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1081 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1083 FREE(ref,unresolved_method);
1086 /******************************************************************************/
1088 /******************************************************************************/
1090 /* unresolved_subtype_set_debug_dump *******************************************
1092 Print debug info for unresolved_subtype_set to stream
1095 stset............the unresolved_subtype_set
1096 file.............the stream
1098 *******************************************************************************/
1101 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1103 classref_or_classinfo *p;
1105 if (SUBTYPESET_IS_EMPTY(*stset)) {
1106 fprintf(file," (empty)\n");
1109 p = stset->subtyperefs;
1110 for (;p->any; ++p) {
1111 if (IS_CLASSREF(*p)) {
1112 fprintf(file," ref: ");
1113 utf_fprint(file,p->ref->name);
1116 fprintf(file," cls: ");
1117 utf_fprint(file,p->cls->name);
1124 /* unresolved_field_debug_dump *************************************************
1126 Print debug info for unresolved_field to stream
1129 ref..............the unresolved_field
1130 file.............the stream
1132 *******************************************************************************/
1135 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1137 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1139 fprintf(file," referer : ");
1140 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1141 fprintf(file," refmethod : ");
1142 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1143 fprintf(file," refmethodd : ");
1144 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1145 fprintf(file," classname : ");
1146 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1147 fprintf(file," name : ");
1148 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1149 fprintf(file," descriptor: ");
1150 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1151 fprintf(file," parseddesc: ");
1152 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1153 fprintf(file," flags : %04x\n",ref->flags);
1154 fprintf(file," instancetypes:\n");
1155 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1156 fprintf(file," valueconstraints:\n");
1157 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1161 /* unresolved_method_debug_dump ************************************************
1163 Print debug info for unresolved_method to stream
1166 ref..............the unresolved_method
1167 file.............the stream
1169 *******************************************************************************/
1172 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1176 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1178 fprintf(file," referer : ");
1179 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1180 fprintf(file," refmethod : ");
1181 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1182 fprintf(file," refmethodd : ");
1183 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1184 fprintf(file," classname : ");
1185 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1186 fprintf(file," name : ");
1187 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1188 fprintf(file," descriptor: ");
1189 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1190 fprintf(file," parseddesc: ");
1191 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1192 fprintf(file," flags : %04x\n",ref->flags);
1193 fprintf(file," instancetypes:\n");
1194 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1195 fprintf(file," paramconstraints:\n");
1196 if (ref->paramconstraints) {
1197 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1198 fprintf(file," param %d:\n",i);
1199 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1203 fprintf(file," (empty)\n");
1209 * These are local overrides for various environment variables in Emacs.
1210 * Please do not remove this and leave it at the end of the file, where
1211 * Emacs will automagically detect them.
1212 * ---------------------------------------------------------------------
1215 * indent-tabs-mode: t
1219 * vim:noexpandtab:sw=4:ts=4: