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 2181 2005-04-01 16:53:33Z edwin $
37 #include "vm/resolve.h"
38 #include "vm/access.h"
39 #include "vm/classcache.h"
40 #include "vm/exceptions.h"
41 #include "vm/linker.h"
42 #include "vm/classcache.h"
43 #include "vm/descriptor.h"
44 #include "vm/jit/jit.h"
45 #include "vm/jit/verify/typeinfo.h"
47 /******************************************************************************/
49 /******************************************************************************/
51 /*#define RESOLVE_VERBOSE*/
58 #define RESOLVE_ASSERT(cond) assert(cond)
60 #define RESOLVE_ASSERT(cond)
63 /******************************************************************************/
64 /* CLASS RESOLUTION */
65 /******************************************************************************/
67 /* resolve symbolic class reference -- see resolve.h */
69 resolve_class(classinfo *referer,methodinfo *refmethod,
74 classinfo *cls = NULL;
78 RESOLVE_ASSERT(result);
79 RESOLVE_ASSERT(referer);
80 RESOLVE_ASSERT(classname);
81 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
85 #ifdef RESOLVE_VERBOSE
86 fprintf(stderr,"resolve_class(");
87 utf_fprint(stderr,referer->name);
89 utf_fprint(stderr,classname);
90 fprintf(stderr,")\n");
93 /* lookup if this class has already been loaded */
94 cls = classcache_lookup(referer->classloader,classname);
96 #ifdef RESOLVE_VERBOSE
97 fprintf(stderr," lookup result: %p\n",(void*)cls);
101 /* resolve array types */
102 if (classname->text[0] == '[') {
103 utf_ptr = classname->text + 1;
104 len = classname->blength - 1;
105 /* classname is an array type name */
112 /* the component type is a reference type */
113 /* resolve the component type */
114 if (!resolve_class(referer,refmethod,
115 utf_new(utf_ptr,len),
117 return false; /* exception */
119 RESOLVE_ASSERT(mode == resolveLazy);
120 return true; /* be lazy */
122 /* create the array class */
123 cls = class_array_of(cls);
127 /* the class has not been loaded, yet */
128 if (mode == resolveLazy)
129 return true; /* be lazy */
132 #ifdef RESOLVE_VERBOSE
133 fprintf(stderr," loading...\n");
138 classinfo *c = class_new(classname);
139 cls = load_class_from_classloader(c,referer->classloader);
142 return false; /* exception */
147 /* the class is now loaded */
149 RESOLVE_ASSERT(cls->loaded);
151 #ifdef RESOLVE_VERBOSE
152 fprintf(stderr," checking access rights...\n");
155 /* check access rights of referer to refered class */
156 if (!is_accessible_class(referer,cls)) {
157 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
158 "class is not accessible XXX add message");
159 return false; /* exception */
162 /* resolution succeeds */
163 #ifdef RESOLVE_VERBOSE
164 fprintf(stderr," success.\n");
171 resolve_classref_or_classinfo(methodinfo *refmethod,
172 classref_or_classinfo cls,
179 RESOLVE_ASSERT(cls.any);
180 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
181 RESOLVE_ASSERT(result);
185 if (IS_CLASSREF(cls)) {
186 /* we must resolve this reference */
187 if (!resolve_class(cls.ref->referer,refmethod,cls.ref->name,
189 return false; /* exception */
192 /* cls has already been resolved */
195 if (!load_class_from_classloader(c, cls.ref->referer->classloader))
196 return false; /* exception */
198 RESOLVE_ASSERT(c || (mode == resolveLazy));
201 return true; /* be lazy */
204 RESOLVE_ASSERT(c->loaded);
209 return false; /* exception */
210 RESOLVE_ASSERT(c->linked);
218 /******************************************************************************/
219 /* SUBTYPE SET CHECKS */
220 /******************************************************************************/
222 /* for documentation see resolve.h */
224 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
225 unresolved_subtype_set *ref,
226 classref_or_classinfo typeref,
232 classref_or_classinfo *setp;
238 RESOLVE_ASSERT(referer);
240 RESOLVE_ASSERT(typeref.any);
241 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
242 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
244 #ifdef RESOLVE_VERBOSE
245 fprintf(stderr,"resolve_and_check_subtype_set\n");
246 unresolved_subtype_set_debug_dump(ref,stderr);
247 if (IS_CLASSREF(typeref)) {
248 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
251 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
253 fprintf(stderr,"\n");
256 setp = ref->subtyperefs;
258 /* an empty set of tests always succeeds */
259 if (!setp || !setp->any) {
268 /* first resolve the type if necessary */
269 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
270 return false; /* exception */
272 return true; /* be lazy */
274 RESOLVE_ASSERT(type);
275 RESOLVE_ASSERT(type->loaded);
276 RESOLVE_ASSERT(type->linked);
277 TYPEINFO_INIT_CLASSINFO(typeti,type);
279 for (; setp->any; ++setp) {
280 /* first resolve the set member if necessary */
281 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
282 return false; /* exception */
284 return true; /* be lazy */
286 RESOLVE_ASSERT(result);
287 RESOLVE_ASSERT(result->loaded);
288 RESOLVE_ASSERT(result->linked);
290 #ifdef RESOLVE_VERBOSE
291 fprintf(stderr,"performing subclass test:\n");
292 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
293 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
294 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
297 /* now check the subtype relationship */
298 TYPEINFO_INIT_CLASSINFO(resultti,result);
300 /* we must test against `true` because `MAYBE` is also != 0 */
301 if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
302 #ifdef RESOLVE_VERBOSE
303 fprintf(stderr,"reversed subclass test failed\n");
309 /* we must test against `true` because `MAYBE` is also != 0 */
310 if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
311 #ifdef RESOLVE_VERBOSE
312 fprintf(stderr,"subclass test failed\n");
325 if (error == resolveIllegalAccessError)
326 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
327 "illegal access to protected member XXX add message");
329 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
330 "subtype constraint violated XXX add message");
331 return false; /* exception */
334 /******************************************************************************/
335 /* FIELD RESOLUTION */
336 /******************************************************************************/
338 /* for documentation see resolve.h */
340 resolve_field(unresolved_field *ref,
345 classinfo *container;
347 constant_classref *fieldtyperef;
352 RESOLVE_ASSERT(result);
353 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
357 #ifdef RESOLVE_VERBOSE
358 unresolved_field_debug_dump(ref,stderr);
361 /* the class containing the reference */
362 referer = ref->fieldref->classref->referer;
363 RESOLVE_ASSERT(referer);
365 /* first we must resolve the class containg the field */
366 if (!resolve_class(referer,ref->referermethod,
367 ref->fieldref->classref->name,mode,&container))
369 /* the class reference could not be resolved */
370 return false; /* exception */
373 return true; /* be lazy */
375 RESOLVE_ASSERT(container);
376 RESOLVE_ASSERT(container->loaded && container->linked);
378 /* now we must find the declaration of the field in `container`
379 * or one of its superclasses */
381 #ifdef RESOLVE_VERBOSE
382 fprintf(stderr," resolving field in class...\n");
385 fi = class_resolvefield(container,
386 ref->fieldref->name,ref->fieldref->descriptor,
389 return false; /* exception */
391 /* { the field reference has been resolved } */
392 declarer = fi->class;
393 RESOLVE_ASSERT(declarer);
394 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
396 #ifdef RESOLVE_VERBOSE
397 fprintf(stderr," checking static...\n");
401 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
402 /* a static field is accessed via an instance, or vice versa */
403 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
404 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
405 : "instance field accessed without instance");
406 return false; /* exception */
409 /* for non-static accesses we have to check the constraints on the instance type */
410 if ((ref->flags & RESOLVE_STATIC) == 0) {
411 #ifdef RESOLVE_VERBOSE
412 fprintf(stderr," checking instance types...\n");
415 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
416 &(ref->instancetypes),
417 CLASSREF_OR_CLASSINFO(container),
420 resolveLinkageError,&checked))
422 return false; /* exception */
425 return true; /* be lazy */
428 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
430 /* for PUT* instructions we have to check the constraints on the value type */
431 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
432 RESOLVE_ASSERT(fieldtyperef);
433 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
434 /* check subtype constraints */
435 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
436 &(ref->valueconstraints),
437 CLASSREF_OR_CLASSINFO(fieldtyperef),
440 resolveLinkageError,&checked))
442 return false; /* exception */
445 return true; /* be lazy */
449 /* check access rights */
450 if (!is_accessible_member(referer,declarer,fi->flags)) {
451 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
452 "field is not accessible XXX add message");
453 return false; /* exception */
456 /* check protected access */
457 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
458 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
459 &(ref->instancetypes),
460 CLASSREF_OR_CLASSINFO(referer),
463 resolveIllegalAccessError,&checked))
465 return false; /* exception */
468 return true; /* be lazy */
471 /* impose loading constraint on field type */
472 if (fi->type == TYPE_ADR) {
473 RESOLVE_ASSERT(fieldtyperef);
474 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
476 return false; /* exception */
484 /******************************************************************************/
485 /* METHOD RESOLUTION */
486 /******************************************************************************/
488 /* for documentation see resolve.h */
490 resolve_method(unresolved_method *ref,
495 classinfo *container;
498 typedesc *paramtypes;
504 RESOLVE_ASSERT(result);
505 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
507 #ifdef RESOLVE_VERBOSE
508 unresolved_method_debug_dump(ref,stderr);
513 /* the class containing the reference */
514 referer = ref->methodref->classref->referer;
515 RESOLVE_ASSERT(referer);
517 /* first we must resolve the class containg the method */
518 if (!resolve_class(referer,ref->referermethod,
519 ref->methodref->classref->name,mode,&container))
521 /* the class reference could not be resolved */
522 return false; /* exception */
525 return true; /* be lazy */
527 RESOLVE_ASSERT(container);
529 /* now we must find the declaration of the method in `container`
530 * or one of its superclasses */
532 if ((container->flags & ACC_INTERFACE) != 0) {
533 mi = class_resolveinterfacemethod(container,
534 ref->methodref->name,ref->methodref->descriptor,
538 mi = class_resolveclassmethod(container,
539 ref->methodref->name,ref->methodref->descriptor,
543 return false; /* exception */ /* XXX set exceptionptr? */
545 /* { the method reference has been resolved } */
546 declarer = mi->class;
547 RESOLVE_ASSERT(declarer);
550 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
551 /* a static method is accessed via an instance, or vice versa */
552 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
553 (mi->flags & ACC_STATIC) ? "static method called via instance"
554 : "instance method called without instance");
555 return false; /* exception */
558 /* for non-static methods we have to check the constraints on the instance type */
559 if ((ref->flags & RESOLVE_STATIC) == 0) {
560 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
561 &(ref->instancetypes),
562 CLASSREF_OR_CLASSINFO(container),
565 resolveLinkageError,&checked))
567 return false; /* exception */
570 return true; /* be lazy */
577 /* check subtype constraints for TYPE_ADR parameters */
578 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
579 paramtypes = ref->methodref->parseddesc.md->paramtypes;
581 for (i=0; i<(mi->paramcount-instancecount); ++i) {
582 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
583 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
584 if (ref->paramconstraints) {
585 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
586 ref->paramconstraints + i,
587 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
590 resolveLinkageError,&checked))
592 return false; /* exception */
595 return true; /* be lazy */
600 /* check access rights */
601 if (!is_accessible_member(referer,declarer,mi->flags)) {
602 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
603 "method is not accessible XXX add message");
604 return false; /* exception */
607 /* check protected access */
608 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
609 /* XXX do we also need to check (referer subclass_of declarer)? */
610 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
611 &(ref->instancetypes),
612 CLASSREF_OR_CLASSINFO(referer),
615 resolveIllegalAccessError,&checked))
617 return false; /* exception */
620 return true; /* be lazy */
623 /* impose loading constraints on parameters (including instance) */
624 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
625 for (i=0; i<mi->paramcount; ++i) {
626 if (mi->paramtypes[i] == TYPE_ADR) {
629 if (i < instancecount)
630 name = container->name; /* XXX should this be declarer->name? */
632 name = paramtypes[i].classref->name;
634 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
635 return false; /* exception */
639 /* impose loading constraing onto return type */
640 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
641 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
642 ref->methodref->parseddesc.md->returntype.classref->name))
643 return false; /* exception */
651 /******************************************************************************/
652 /* CREATING THE DATA STRUCTURES */
653 /******************************************************************************/
656 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
657 unresolved_subtype_set *stset,typeinfo *tinfo,
658 constant_classref *declaredtype)
663 RESOLVE_ASSERT(stset);
664 RESOLVE_ASSERT(tinfo);
666 #ifdef RESOLVE_VERBOSE
667 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
668 #ifdef TYPEINFO_DEBUG
669 typeinfo_print(stderr,tinfo,4);
670 fprintf(stderr,"\n");
672 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
673 fprintf(stderr,"\n");
676 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
677 *exceptionptr = new_verifyerror(refmethod,
678 "Invalid use of returnAddress");
682 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
683 *exceptionptr = new_verifyerror(refmethod,
684 "Invalid use of uninitialized object");
688 /* the nulltype is always assignable (XXX for reversed?) */
689 if (TYPEINFO_IS_NULLTYPE(*tinfo))
692 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
693 if (declaredtype->name == utf_java_lang_Object
694 && referer->classloader == NULL)
700 count = tinfo->merged->count;
701 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
702 for (i=0; i<count; ++i) {
703 stset->subtyperefs[i] = tinfo->merged->list[i];
705 stset->subtyperefs[count].any = NULL; /* terminate */
708 if ((IS_CLASSREF(tinfo->typeclass)
709 ? tinfo->typeclass.ref->name
710 : tinfo->typeclass.cls->name) == declaredtype->name)
715 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
716 stset->subtyperefs[0] = tinfo->typeclass;
717 stset->subtyperefs[1].any = NULL; /* terminate */
724 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
729 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
733 unresolved_field *ref;
734 constant_FMIref *fieldref = NULL;
735 stackelement *instanceslot = NULL;
738 typeinfo *tip = NULL;
741 #ifdef RESOLVE_VERBOSE
742 fprintf(stderr,"create_unresolved_field\n");
743 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
744 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
745 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
748 ref = NEW(unresolved_field);
750 ref->referermethod = refmethod;
752 switch (iptr[0].opc) {
754 ref->flags |= RESOLVE_PUTFIELD;
755 instanceslot = stack->prev;
756 tip = &(stack->typeinfo);
757 fieldref = (constant_FMIref *) iptr[0].val.a;
760 case ICMD_PUTFIELDCONST:
761 ref->flags |= RESOLVE_PUTFIELD;
762 instanceslot = stack;
763 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
767 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
768 fieldref = (constant_FMIref *) iptr[0].val.a;
769 tip = &(stack->typeinfo);
772 case ICMD_PUTSTATICCONST:
773 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
774 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
778 instanceslot = stack;
779 fieldref = (constant_FMIref *) iptr[0].val.a;
783 ref->flags |= RESOLVE_STATIC;
784 fieldref = (constant_FMIref *) iptr[0].val.a;
788 RESOLVE_ASSERT(fieldref);
789 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
790 fd = fieldref->parseddesc.fd;
793 #ifdef RESOLVE_VERBOSE
794 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
795 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
796 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
797 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
799 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
802 ref->fieldref = fieldref;
804 /* record subtype constraints for the instance type, if any */
807 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
809 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
810 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
812 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
813 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
814 : refmethod->class; /* XXX classrefs */
815 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
816 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
820 insttip = &(instanceslot->typeinfo);
822 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
823 &(ref->instancetypes),insttip,fieldref->classref))
827 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
830 /* record subtype constraints for the value type, if any */
832 if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
834 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
836 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
837 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
840 TYPEINFO_INIT_NULLTYPE(tinfo);
842 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
843 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
847 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
854 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
858 unresolved_method *ref;
859 constant_FMIref *methodref;
860 stackelement *instanceslot = NULL;
867 methodref = (constant_FMIref *) iptr[0].val.a;
868 RESOLVE_ASSERT(methodref);
869 md = methodref->parseddesc.md;
872 #ifdef RESOLVE_VERBOSE
873 fprintf(stderr,"create_unresolved_method\n");
874 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
875 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
876 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
877 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
878 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
879 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
880 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
883 ref = NEW(unresolved_method);
885 ref->referermethod = refmethod;
886 ref->methodref = methodref;
887 ref->paramconstraints = NULL;
889 switch (iptr[0].opc) {
890 case ICMD_INVOKESTATIC:
891 ref->flags |= RESOLVE_STATIC;
893 case ICMD_INVOKEVIRTUAL:
894 case ICMD_INVOKESPECIAL:
895 case ICMD_INVOKEINTERFACE:
898 RESOLVE_ASSERT(false);
901 if ((ref->flags & RESOLVE_STATIC) == 0) {
902 /* find the instance slot under all the parameter slots on the stack */
903 instanceslot = stack;
904 for (i=0; i<md->paramcount; ++i)
905 instanceslot = instanceslot->prev;
908 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
910 /* record subtype constraints for the instance type, if any */
914 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
916 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
917 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
919 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
920 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
921 : refmethod->class; /* XXX classrefs */
922 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
923 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
927 tip = &(instanceslot->typeinfo);
929 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
930 &(ref->instancetypes),tip,methodref->classref))
934 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
937 /* record subtype constraints for the parameter types, if any */
939 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
940 type = md->paramtypes[i].type;
942 RESOLVE_ASSERT(param);
943 RESOLVE_ASSERT(type == param->type);
945 if (type == TYPE_ADR) {
946 if (!ref->paramconstraints) {
947 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
948 for (j=md->paramcount-1; j>i; --j)
949 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
951 RESOLVE_ASSERT(ref->paramconstraints);
952 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
953 ref->paramconstraints + i,&(param->typeinfo),
954 md->paramtypes[i].classref))
958 if (ref->paramconstraints)
959 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
966 /******************************************************************************/
968 /******************************************************************************/
971 unresolved_subtype_set_free_list(classref_or_classinfo *list)
974 classref_or_classinfo *p = list;
976 /* this is silly. we *only* need to count the elements for MFREE */
979 MFREE(list,classref_or_classinfo,(p - list));
983 /* unresolved_field_free *******************************************************
985 Free the memory used by an unresolved_field
988 ref..............the unresolved_field
990 *******************************************************************************/
993 unresolved_field_free(unresolved_field *ref)
997 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
998 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
999 FREE(ref,unresolved_field);
1002 /* unresolved_method_free ******************************************************
1004 Free the memory used by an unresolved_method
1007 ref..............the unresolved_method
1009 *******************************************************************************/
1012 unresolved_method_free(unresolved_method *ref)
1014 RESOLVE_ASSERT(ref);
1016 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1017 if (ref->paramconstraints) {
1019 int count = ref->methodref->parseddesc.md->paramcount;
1021 for (i=0; i<count; ++i)
1022 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1023 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1025 FREE(ref,unresolved_method);
1028 /******************************************************************************/
1030 /******************************************************************************/
1032 /* unresolved_subtype_set_debug_dump *******************************************
1034 Print debug info for unresolved_subtype_set to stream
1037 stset............the unresolved_subtype_set
1038 file.............the stream
1040 *******************************************************************************/
1043 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1045 classref_or_classinfo *p;
1047 if (SUBTYPESET_IS_EMPTY(*stset)) {
1048 fprintf(file," (empty)\n");
1051 p = stset->subtyperefs;
1052 for (;p->any; ++p) {
1053 if (IS_CLASSREF(*p)) {
1054 fprintf(file," ref: ");
1055 utf_fprint(file,p->ref->name);
1058 fprintf(file," cls: ");
1059 utf_fprint(file,p->cls->name);
1066 /* unresolved_field_debug_dump *************************************************
1068 Print debug info for unresolved_field to stream
1071 ref..............the unresolved_field
1072 file.............the stream
1074 *******************************************************************************/
1077 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1079 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1081 fprintf(file," referer : ");
1082 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1083 fprintf(file," refmethod : ");
1084 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1085 fprintf(file," refmethodd : ");
1086 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1087 fprintf(file," classname : ");
1088 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1089 fprintf(file," name : ");
1090 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1091 fprintf(file," descriptor: ");
1092 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1093 fprintf(file," parseddesc: ");
1094 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1095 fprintf(file," flags : %04x\n",ref->flags);
1096 fprintf(file," instancetypes:\n");
1097 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1098 fprintf(file," valueconstraints:\n");
1099 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1103 /* unresolved_method_debug_dump ************************************************
1105 Print debug info for unresolved_method to stream
1108 ref..............the unresolved_method
1109 file.............the stream
1111 *******************************************************************************/
1114 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1118 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1120 fprintf(file," referer : ");
1121 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1122 fprintf(file," refmethod : ");
1123 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1124 fprintf(file," refmethodd : ");
1125 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1126 fprintf(file," classname : ");
1127 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1128 fprintf(file," name : ");
1129 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1130 fprintf(file," descriptor: ");
1131 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1132 fprintf(file," parseddesc: ");
1133 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1134 fprintf(file," flags : %04x\n",ref->flags);
1135 fprintf(file," instancetypes:\n");
1136 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1137 fprintf(file," paramconstraints:\n");
1138 if (ref->paramconstraints) {
1139 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1140 fprintf(file," param %d:\n",i);
1141 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1145 fprintf(file," (empty)\n");
1151 * These are local overrides for various environment variables in Emacs.
1152 * Please do not remove this and leave it at the end of the file, where
1153 * Emacs will automagically detect them.
1154 * ---------------------------------------------------------------------
1157 * indent-tabs-mode: t
1161 * vim:noexpandtab:sw=4:ts=4: