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 2189 2005-04-02 02:05:59Z edwin $
37 #include "vm/resolve.h"
38 #include "vm/access.h"
39 #include "vm/classcache.h"
40 #include "vm/exceptions.h"
41 #include "vm/loader.h"
42 #include "vm/linker.h"
43 #include "vm/classcache.h"
44 #include "vm/descriptor.h"
45 #include "vm/jit/jit.h"
46 #include "vm/jit/verify/typeinfo.h"
48 /******************************************************************************/
50 /******************************************************************************/
52 /*#define RESOLVE_VERBOSE*/
59 #define RESOLVE_ASSERT(cond) assert(cond)
61 #define RESOLVE_ASSERT(cond)
64 /******************************************************************************/
65 /* CLASS RESOLUTION */
66 /******************************************************************************/
68 /* resolve symbolic class reference -- see resolve.h */
70 resolve_class(classinfo *referer,methodinfo *refmethod,
75 classinfo *cls = NULL;
79 RESOLVE_ASSERT(result);
80 RESOLVE_ASSERT(referer);
81 RESOLVE_ASSERT(classname);
82 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
86 #ifdef RESOLVE_VERBOSE
87 fprintf(stderr,"resolve_class(");
88 utf_fprint(stderr,referer->name);
90 utf_fprint(stderr,classname);
91 fprintf(stderr,")\n");
94 /* lookup if this class has already been loaded */
95 cls = classcache_lookup(referer->classloader,classname);
97 #ifdef RESOLVE_VERBOSE
98 fprintf(stderr," lookup result: %p\n",(void*)cls);
102 /* resolve array types */
103 if (classname->text[0] == '[') {
104 utf_ptr = classname->text + 1;
105 len = classname->blength - 1;
106 /* classname is an array type name */
113 /* the component type is a reference type */
114 /* resolve the component type */
115 if (!resolve_class(referer,refmethod,
116 utf_new(utf_ptr,len),
118 return false; /* exception */
120 RESOLVE_ASSERT(mode == resolveLazy);
121 return true; /* be lazy */
123 /* create the array class */
124 cls = class_array_of(cls);
128 /* the class has not been loaded, yet */
129 if (mode == resolveLazy)
130 return true; /* be lazy */
133 #ifdef RESOLVE_VERBOSE
134 fprintf(stderr," loading...\n");
139 classinfo *c = class_new(classname);
140 cls = load_class_from_classloader(c,referer->classloader);
143 return false; /* exception */
148 /* the class is now loaded */
150 RESOLVE_ASSERT(cls->loaded);
152 #ifdef RESOLVE_VERBOSE
153 fprintf(stderr," checking access rights...\n");
156 /* check access rights of referer to refered class */
157 if (!is_accessible_class(referer,cls)) {
158 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
159 "class is not accessible XXX add message");
160 return false; /* exception */
163 /* resolution succeeds */
164 #ifdef RESOLVE_VERBOSE
165 fprintf(stderr," success.\n");
172 resolve_classref(methodinfo *refmethod,
173 constant_classref *ref,
178 return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
182 resolve_classref_or_classinfo(methodinfo *refmethod,
183 classref_or_classinfo cls,
190 RESOLVE_ASSERT(cls.any);
191 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
192 RESOLVE_ASSERT(result);
196 if (IS_CLASSREF(cls)) {
197 /* we must resolve this reference */
198 if (!resolve_class(cls.ref->referer,refmethod,cls.ref->name,
200 return false; /* exception */
203 /* cls has already been resolved */
206 if (!load_class_from_classloader(c, cls.ref->referer->classloader))
207 return false; /* exception */
209 RESOLVE_ASSERT(c || (mode == resolveLazy));
212 return true; /* be lazy */
215 RESOLVE_ASSERT(c->loaded);
220 return false; /* exception */
221 RESOLVE_ASSERT(c->linked);
230 resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
235 RESOLVE_ASSERT(result);
239 #ifdef RESOLVE_VERBOSE
240 fprintf(stderr,"resolve_class_from_typedesc(");
241 descriptor_debug_print_typedesc(stderr,d);
242 fprintf(stderr,",%i)\n",link);
246 /* a reference type */
247 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
248 resolveEager,link,&cls))
249 return false; /* exception */
252 /* a primitive type */
253 cls = primitivetype_table[d->decltype].class_primitive;
254 RESOLVE_ASSERT(cls->loaded);
256 if (!link_class(cls))
257 return false; /* exception */
260 RESOLVE_ASSERT(cls->loaded);
261 RESOLVE_ASSERT(!link || cls->linked);
263 #ifdef RESOLVE_VERBOSE
264 fprintf(stderr," result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
271 /******************************************************************************/
272 /* SUBTYPE SET CHECKS */
273 /******************************************************************************/
275 /* for documentation see resolve.h */
277 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
278 unresolved_subtype_set *ref,
279 classref_or_classinfo typeref,
285 classref_or_classinfo *setp;
291 RESOLVE_ASSERT(referer);
293 RESOLVE_ASSERT(typeref.any);
294 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
295 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
297 #ifdef RESOLVE_VERBOSE
298 fprintf(stderr,"resolve_and_check_subtype_set\n");
299 unresolved_subtype_set_debug_dump(ref,stderr);
300 if (IS_CLASSREF(typeref)) {
301 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
304 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
306 fprintf(stderr,"\n");
309 setp = ref->subtyperefs;
311 /* an empty set of tests always succeeds */
312 if (!setp || !setp->any) {
321 /* first resolve the type if necessary */
322 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
323 return false; /* exception */
325 return true; /* be lazy */
327 RESOLVE_ASSERT(type);
328 RESOLVE_ASSERT(type->loaded);
329 RESOLVE_ASSERT(type->linked);
330 TYPEINFO_INIT_CLASSINFO(typeti,type);
332 for (; setp->any; ++setp) {
333 /* first resolve the set member if necessary */
334 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
335 return false; /* exception */
337 return true; /* be lazy */
339 RESOLVE_ASSERT(result);
340 RESOLVE_ASSERT(result->loaded);
341 RESOLVE_ASSERT(result->linked);
343 #ifdef RESOLVE_VERBOSE
344 fprintf(stderr,"performing subclass test:\n");
345 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
346 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
347 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
350 /* now check the subtype relationship */
351 TYPEINFO_INIT_CLASSINFO(resultti,result);
353 /* we must test against `true` because `MAYBE` is also != 0 */
354 if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
355 #ifdef RESOLVE_VERBOSE
356 fprintf(stderr,"reversed subclass test failed\n");
362 /* we must test against `true` because `MAYBE` is also != 0 */
363 if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
364 #ifdef RESOLVE_VERBOSE
365 fprintf(stderr,"subclass test failed\n");
378 if (error == resolveIllegalAccessError)
379 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
380 "illegal access to protected member XXX add message");
382 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
383 "subtype constraint violated XXX add message");
384 return false; /* exception */
387 /******************************************************************************/
388 /* FIELD RESOLUTION */
389 /******************************************************************************/
391 /* for documentation see resolve.h */
393 resolve_field(unresolved_field *ref,
398 classinfo *container;
400 constant_classref *fieldtyperef;
405 RESOLVE_ASSERT(result);
406 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
410 #ifdef RESOLVE_VERBOSE
411 unresolved_field_debug_dump(ref,stderr);
414 /* the class containing the reference */
415 referer = ref->fieldref->classref->referer;
416 RESOLVE_ASSERT(referer);
418 /* first we must resolve the class containg the field */
419 if (!resolve_class(referer,ref->referermethod,
420 ref->fieldref->classref->name,mode,&container))
422 /* the class reference could not be resolved */
423 return false; /* exception */
426 return true; /* be lazy */
428 RESOLVE_ASSERT(container);
429 RESOLVE_ASSERT(container->loaded && container->linked);
431 /* now we must find the declaration of the field in `container`
432 * or one of its superclasses */
434 #ifdef RESOLVE_VERBOSE
435 fprintf(stderr," resolving field in class...\n");
438 fi = class_resolvefield(container,
439 ref->fieldref->name,ref->fieldref->descriptor,
442 return false; /* exception */
444 /* { the field reference has been resolved } */
445 declarer = fi->class;
446 RESOLVE_ASSERT(declarer);
447 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
449 #ifdef RESOLVE_VERBOSE
450 fprintf(stderr," checking static...\n");
454 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
455 /* a static field is accessed via an instance, or vice versa */
456 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
457 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
458 : "instance field accessed without instance");
459 return false; /* exception */
462 /* for non-static accesses we have to check the constraints on the instance type */
463 if ((ref->flags & RESOLVE_STATIC) == 0) {
464 #ifdef RESOLVE_VERBOSE
465 fprintf(stderr," checking instance types...\n");
468 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
469 &(ref->instancetypes),
470 CLASSREF_OR_CLASSINFO(container),
473 resolveLinkageError,&checked))
475 return false; /* exception */
478 return true; /* be lazy */
481 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
483 /* for PUT* instructions we have to check the constraints on the value type */
484 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
485 RESOLVE_ASSERT(fieldtyperef);
486 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
487 /* check subtype constraints */
488 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
489 &(ref->valueconstraints),
490 CLASSREF_OR_CLASSINFO(fieldtyperef),
493 resolveLinkageError,&checked))
495 return false; /* exception */
498 return true; /* be lazy */
502 /* check access rights */
503 if (!is_accessible_member(referer,declarer,fi->flags)) {
504 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
505 "field is not accessible XXX add message");
506 return false; /* exception */
509 /* check protected access */
510 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
511 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
512 &(ref->instancetypes),
513 CLASSREF_OR_CLASSINFO(referer),
516 resolveIllegalAccessError,&checked))
518 return false; /* exception */
521 return true; /* be lazy */
524 /* impose loading constraint on field type */
525 if (fi->type == TYPE_ADR) {
526 RESOLVE_ASSERT(fieldtyperef);
527 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
529 return false; /* exception */
537 /******************************************************************************/
538 /* METHOD RESOLUTION */
539 /******************************************************************************/
541 /* for documentation see resolve.h */
543 resolve_method(unresolved_method *ref,
548 classinfo *container;
551 typedesc *paramtypes;
557 RESOLVE_ASSERT(result);
558 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
560 #ifdef RESOLVE_VERBOSE
561 unresolved_method_debug_dump(ref,stderr);
566 /* the class containing the reference */
567 referer = ref->methodref->classref->referer;
568 RESOLVE_ASSERT(referer);
570 /* first we must resolve the class containg the method */
571 if (!resolve_class(referer,ref->referermethod,
572 ref->methodref->classref->name,mode,&container))
574 /* the class reference could not be resolved */
575 return false; /* exception */
578 return true; /* be lazy */
580 RESOLVE_ASSERT(container);
582 /* now we must find the declaration of the method in `container`
583 * or one of its superclasses */
585 if ((container->flags & ACC_INTERFACE) != 0) {
586 mi = class_resolveinterfacemethod(container,
587 ref->methodref->name,ref->methodref->descriptor,
591 mi = class_resolveclassmethod(container,
592 ref->methodref->name,ref->methodref->descriptor,
596 return false; /* exception */ /* XXX set exceptionptr? */
598 /* { the method reference has been resolved } */
599 declarer = mi->class;
600 RESOLVE_ASSERT(declarer);
603 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
604 /* a static method is accessed via an instance, or vice versa */
605 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
606 (mi->flags & ACC_STATIC) ? "static method called via instance"
607 : "instance method called without instance");
608 return false; /* exception */
611 /* for non-static methods we have to check the constraints on the instance type */
612 if ((ref->flags & RESOLVE_STATIC) == 0) {
613 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
614 &(ref->instancetypes),
615 CLASSREF_OR_CLASSINFO(container),
618 resolveLinkageError,&checked))
620 return false; /* exception */
623 return true; /* be lazy */
630 /* check subtype constraints for TYPE_ADR parameters */
631 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
632 paramtypes = ref->methodref->parseddesc.md->paramtypes;
634 for (i=0; i<(mi->paramcount-instancecount); ++i) {
635 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
636 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
637 if (ref->paramconstraints) {
638 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
639 ref->paramconstraints + i,
640 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
643 resolveLinkageError,&checked))
645 return false; /* exception */
648 return true; /* be lazy */
653 /* check access rights */
654 if (!is_accessible_member(referer,declarer,mi->flags)) {
655 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
656 "method is not accessible XXX add message");
657 return false; /* exception */
660 /* check protected access */
661 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
662 /* XXX do we also need to check (referer subclass_of declarer)? */
663 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
664 &(ref->instancetypes),
665 CLASSREF_OR_CLASSINFO(referer),
668 resolveIllegalAccessError,&checked))
670 return false; /* exception */
673 return true; /* be lazy */
676 /* impose loading constraints on parameters (including instance) */
677 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
678 for (i=0; i<mi->paramcount; ++i) {
679 if (mi->paramtypes[i] == TYPE_ADR) {
682 if (i < instancecount)
683 name = container->name; /* XXX should this be declarer->name? */
685 name = paramtypes[i].classref->name;
687 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
688 return false; /* exception */
692 /* impose loading constraing onto return type */
693 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
694 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
695 ref->methodref->parseddesc.md->returntype.classref->name))
696 return false; /* exception */
704 /******************************************************************************/
705 /* CREATING THE DATA STRUCTURES */
706 /******************************************************************************/
709 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
710 unresolved_subtype_set *stset,typeinfo *tinfo,
711 constant_classref *declaredtype)
716 RESOLVE_ASSERT(stset);
717 RESOLVE_ASSERT(tinfo);
719 #ifdef RESOLVE_VERBOSE
720 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
721 #ifdef TYPEINFO_DEBUG
722 typeinfo_print(stderr,tinfo,4);
723 fprintf(stderr,"\n");
725 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
726 fprintf(stderr,"\n");
729 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
730 *exceptionptr = new_verifyerror(refmethod,
731 "Invalid use of returnAddress");
735 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
736 *exceptionptr = new_verifyerror(refmethod,
737 "Invalid use of uninitialized object");
741 /* the nulltype is always assignable (XXX for reversed?) */
742 if (TYPEINFO_IS_NULLTYPE(*tinfo))
745 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
746 if (declaredtype->name == utf_java_lang_Object
747 && referer->classloader == NULL)
753 count = tinfo->merged->count;
754 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
755 for (i=0; i<count; ++i) {
756 stset->subtyperefs[i] = tinfo->merged->list[i];
758 stset->subtyperefs[count].any = NULL; /* terminate */
761 if ((IS_CLASSREF(tinfo->typeclass)
762 ? tinfo->typeclass.ref->name
763 : tinfo->typeclass.cls->name) == declaredtype->name)
768 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
769 stset->subtyperefs[0] = tinfo->typeclass;
770 stset->subtyperefs[1].any = NULL; /* terminate */
777 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
782 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
786 unresolved_field *ref;
787 constant_FMIref *fieldref = NULL;
788 stackelement *instanceslot = NULL;
791 typeinfo *tip = NULL;
794 #ifdef RESOLVE_VERBOSE
795 fprintf(stderr,"create_unresolved_field\n");
796 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
797 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
798 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
801 ref = NEW(unresolved_field);
803 ref->referermethod = refmethod;
805 switch (iptr[0].opc) {
807 ref->flags |= RESOLVE_PUTFIELD;
808 instanceslot = stack->prev;
809 tip = &(stack->typeinfo);
810 fieldref = (constant_FMIref *) iptr[0].val.a;
813 case ICMD_PUTFIELDCONST:
814 ref->flags |= RESOLVE_PUTFIELD;
815 instanceslot = stack;
816 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
820 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
821 fieldref = (constant_FMIref *) iptr[0].val.a;
822 tip = &(stack->typeinfo);
825 case ICMD_PUTSTATICCONST:
826 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
827 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
831 instanceslot = stack;
832 fieldref = (constant_FMIref *) iptr[0].val.a;
836 ref->flags |= RESOLVE_STATIC;
837 fieldref = (constant_FMIref *) iptr[0].val.a;
841 RESOLVE_ASSERT(fieldref);
842 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
843 fd = fieldref->parseddesc.fd;
846 #ifdef RESOLVE_VERBOSE
847 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
848 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
849 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
850 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
852 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
855 ref->fieldref = fieldref;
857 /* record subtype constraints for the instance type, if any */
860 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
862 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
863 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
865 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
866 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
867 : refmethod->class; /* XXX classrefs */
868 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
869 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
873 insttip = &(instanceslot->typeinfo);
875 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
876 &(ref->instancetypes),insttip,fieldref->classref))
880 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
883 /* record subtype constraints for the value type, if any */
885 if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
887 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
889 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
890 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
893 TYPEINFO_INIT_NULLTYPE(tinfo);
895 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
896 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
900 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
907 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
911 unresolved_method *ref;
912 constant_FMIref *methodref;
913 stackelement *instanceslot = NULL;
920 methodref = (constant_FMIref *) iptr[0].val.a;
921 RESOLVE_ASSERT(methodref);
922 md = methodref->parseddesc.md;
925 #ifdef RESOLVE_VERBOSE
926 fprintf(stderr,"create_unresolved_method\n");
927 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
928 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
929 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
930 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
931 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
932 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
933 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
936 ref = NEW(unresolved_method);
938 ref->referermethod = refmethod;
939 ref->methodref = methodref;
940 ref->paramconstraints = NULL;
942 switch (iptr[0].opc) {
943 case ICMD_INVOKESTATIC:
944 ref->flags |= RESOLVE_STATIC;
946 case ICMD_INVOKEVIRTUAL:
947 case ICMD_INVOKESPECIAL:
948 case ICMD_INVOKEINTERFACE:
951 RESOLVE_ASSERT(false);
954 if ((ref->flags & RESOLVE_STATIC) == 0) {
955 /* find the instance slot under all the parameter slots on the stack */
956 instanceslot = stack;
957 for (i=0; i<md->paramcount; ++i)
958 instanceslot = instanceslot->prev;
961 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
963 /* record subtype constraints for the instance type, if any */
967 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
969 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
970 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
972 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
973 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
974 : refmethod->class; /* XXX classrefs */
975 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
976 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
980 tip = &(instanceslot->typeinfo);
982 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
983 &(ref->instancetypes),tip,methodref->classref))
987 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
990 /* record subtype constraints for the parameter types, if any */
992 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
993 type = md->paramtypes[i].type;
995 RESOLVE_ASSERT(param);
996 RESOLVE_ASSERT(type == param->type);
998 if (type == TYPE_ADR) {
999 if (!ref->paramconstraints) {
1000 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1001 for (j=md->paramcount-1; j>i; --j)
1002 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1004 RESOLVE_ASSERT(ref->paramconstraints);
1005 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1006 ref->paramconstraints + i,&(param->typeinfo),
1007 md->paramtypes[i].classref))
1011 if (ref->paramconstraints)
1012 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1019 /******************************************************************************/
1020 /* FREEING MEMORY */
1021 /******************************************************************************/
1024 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1027 classref_or_classinfo *p = list;
1029 /* this is silly. we *only* need to count the elements for MFREE */
1032 MFREE(list,classref_or_classinfo,(p - list));
1036 /* unresolved_field_free *******************************************************
1038 Free the memory used by an unresolved_field
1041 ref..............the unresolved_field
1043 *******************************************************************************/
1046 unresolved_field_free(unresolved_field *ref)
1048 RESOLVE_ASSERT(ref);
1050 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1051 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1052 FREE(ref,unresolved_field);
1055 /* unresolved_method_free ******************************************************
1057 Free the memory used by an unresolved_method
1060 ref..............the unresolved_method
1062 *******************************************************************************/
1065 unresolved_method_free(unresolved_method *ref)
1067 RESOLVE_ASSERT(ref);
1069 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1070 if (ref->paramconstraints) {
1072 int count = ref->methodref->parseddesc.md->paramcount;
1074 for (i=0; i<count; ++i)
1075 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1076 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1078 FREE(ref,unresolved_method);
1081 /******************************************************************************/
1083 /******************************************************************************/
1085 /* unresolved_subtype_set_debug_dump *******************************************
1087 Print debug info for unresolved_subtype_set to stream
1090 stset............the unresolved_subtype_set
1091 file.............the stream
1093 *******************************************************************************/
1096 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1098 classref_or_classinfo *p;
1100 if (SUBTYPESET_IS_EMPTY(*stset)) {
1101 fprintf(file," (empty)\n");
1104 p = stset->subtyperefs;
1105 for (;p->any; ++p) {
1106 if (IS_CLASSREF(*p)) {
1107 fprintf(file," ref: ");
1108 utf_fprint(file,p->ref->name);
1111 fprintf(file," cls: ");
1112 utf_fprint(file,p->cls->name);
1119 /* unresolved_field_debug_dump *************************************************
1121 Print debug info for unresolved_field to stream
1124 ref..............the unresolved_field
1125 file.............the stream
1127 *******************************************************************************/
1130 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1132 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1134 fprintf(file," referer : ");
1135 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1136 fprintf(file," refmethod : ");
1137 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1138 fprintf(file," refmethodd : ");
1139 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1140 fprintf(file," classname : ");
1141 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1142 fprintf(file," name : ");
1143 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1144 fprintf(file," descriptor: ");
1145 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1146 fprintf(file," parseddesc: ");
1147 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1148 fprintf(file," flags : %04x\n",ref->flags);
1149 fprintf(file," instancetypes:\n");
1150 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1151 fprintf(file," valueconstraints:\n");
1152 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1156 /* unresolved_method_debug_dump ************************************************
1158 Print debug info for unresolved_method to stream
1161 ref..............the unresolved_method
1162 file.............the stream
1164 *******************************************************************************/
1167 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1171 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1173 fprintf(file," referer : ");
1174 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1175 fprintf(file," refmethod : ");
1176 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1177 fprintf(file," refmethodd : ");
1178 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1179 fprintf(file," classname : ");
1180 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1181 fprintf(file," name : ");
1182 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1183 fprintf(file," descriptor: ");
1184 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1185 fprintf(file," parseddesc: ");
1186 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1187 fprintf(file," flags : %04x\n",ref->flags);
1188 fprintf(file," instancetypes:\n");
1189 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1190 fprintf(file," paramconstraints:\n");
1191 if (ref->paramconstraints) {
1192 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1193 fprintf(file," param %d:\n",i);
1194 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1198 fprintf(file," (empty)\n");
1204 * These are local overrides for various environment variables in Emacs.
1205 * Please do not remove this and leave it at the end of the file, where
1206 * Emacs will automagically detect them.
1207 * ---------------------------------------------------------------------
1210 * indent-tabs-mode: t
1214 * vim:noexpandtab:sw=4:ts=4: