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 2194 2005-04-03 16:13:27Z twisti $
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);
131 /* the class has not been loaded, yet */
132 if (mode == resolveLazy)
133 return true; /* be lazy */
136 #ifdef RESOLVE_VERBOSE
137 fprintf(stderr," loading...\n");
142 if (!load_class_from_classloader(classname,referer->classloader,&cls))
143 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(methodinfo *refmethod,
172 constant_classref *ref,
177 return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
181 resolve_classref_or_classinfo(methodinfo *refmethod,
182 classref_or_classinfo cls,
189 RESOLVE_ASSERT(cls.any);
190 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
191 RESOLVE_ASSERT(result);
195 if (IS_CLASSREF(cls)) {
196 /* we must resolve this reference */
197 if (!resolve_class(cls.ref->referer,refmethod,cls.ref->name,
199 return false; /* exception */
202 /* cls has already been resolved */
204 RESOLVE_ASSERT(c->loaded);
206 RESOLVE_ASSERT(c || (mode == resolveLazy));
209 return true; /* be lazy */
212 RESOLVE_ASSERT(c->loaded);
217 return false; /* exception */
218 RESOLVE_ASSERT(c->linked);
227 resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
232 RESOLVE_ASSERT(result);
236 #ifdef RESOLVE_VERBOSE
237 fprintf(stderr,"resolve_class_from_typedesc(");
238 descriptor_debug_print_typedesc(stderr,d);
239 fprintf(stderr,",%i)\n",link);
243 /* a reference type */
244 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
245 resolveEager,link,&cls))
246 return false; /* exception */
249 /* a primitive type */
250 cls = primitivetype_table[d->decltype].class_primitive;
251 RESOLVE_ASSERT(cls->loaded);
253 if (!link_class(cls))
254 return false; /* exception */
257 RESOLVE_ASSERT(cls->loaded);
258 RESOLVE_ASSERT(!link || cls->linked);
260 #ifdef RESOLVE_VERBOSE
261 fprintf(stderr," result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
268 /******************************************************************************/
269 /* SUBTYPE SET CHECKS */
270 /******************************************************************************/
272 /* for documentation see resolve.h */
274 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
275 unresolved_subtype_set *ref,
276 classref_or_classinfo typeref,
282 classref_or_classinfo *setp;
288 RESOLVE_ASSERT(referer);
290 RESOLVE_ASSERT(typeref.any);
291 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
292 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
294 #ifdef RESOLVE_VERBOSE
295 fprintf(stderr,"resolve_and_check_subtype_set\n");
296 unresolved_subtype_set_debug_dump(ref,stderr);
297 if (IS_CLASSREF(typeref)) {
298 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
301 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
303 fprintf(stderr,"\n");
306 setp = ref->subtyperefs;
308 /* an empty set of tests always succeeds */
309 if (!setp || !setp->any) {
318 /* first resolve the type if necessary */
319 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
320 return false; /* exception */
322 return true; /* be lazy */
324 RESOLVE_ASSERT(type);
325 RESOLVE_ASSERT(type->loaded);
326 RESOLVE_ASSERT(type->linked);
327 TYPEINFO_INIT_CLASSINFO(typeti,type);
329 for (; setp->any; ++setp) {
330 /* first resolve the set member if necessary */
331 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
332 return false; /* exception */
334 return true; /* be lazy */
336 RESOLVE_ASSERT(result);
337 RESOLVE_ASSERT(result->loaded);
338 RESOLVE_ASSERT(result->linked);
340 #ifdef RESOLVE_VERBOSE
341 fprintf(stderr,"performing subclass test:\n");
342 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
343 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
344 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
347 /* now check the subtype relationship */
348 TYPEINFO_INIT_CLASSINFO(resultti,result);
350 /* we must test against `true` because `MAYBE` is also != 0 */
351 if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
352 #ifdef RESOLVE_VERBOSE
353 fprintf(stderr,"reversed subclass test failed\n");
359 /* we must test against `true` because `MAYBE` is also != 0 */
360 if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
361 #ifdef RESOLVE_VERBOSE
362 fprintf(stderr,"subclass test failed\n");
375 if (error == resolveIllegalAccessError)
376 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
377 "illegal access to protected member XXX add message");
379 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
380 "subtype constraint violated XXX add message");
381 return false; /* exception */
384 /******************************************************************************/
385 /* FIELD RESOLUTION */
386 /******************************************************************************/
388 /* for documentation see resolve.h */
390 resolve_field(unresolved_field *ref,
395 classinfo *container;
397 constant_classref *fieldtyperef;
402 RESOLVE_ASSERT(result);
403 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
407 #ifdef RESOLVE_VERBOSE
408 unresolved_field_debug_dump(ref,stderr);
411 /* the class containing the reference */
412 referer = ref->fieldref->classref->referer;
413 RESOLVE_ASSERT(referer);
415 /* first we must resolve the class containg the field */
416 if (!resolve_class(referer,ref->referermethod,
417 ref->fieldref->classref->name,mode,&container))
419 /* the class reference could not be resolved */
420 return false; /* exception */
423 return true; /* be lazy */
425 RESOLVE_ASSERT(container);
426 RESOLVE_ASSERT(container->loaded && container->linked);
428 /* now we must find the declaration of the field in `container`
429 * or one of its superclasses */
431 #ifdef RESOLVE_VERBOSE
432 fprintf(stderr," resolving field in class...\n");
435 fi = class_resolvefield(container,
436 ref->fieldref->name,ref->fieldref->descriptor,
439 return false; /* exception */
441 /* { the field reference has been resolved } */
442 declarer = fi->class;
443 RESOLVE_ASSERT(declarer);
444 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
446 #ifdef RESOLVE_VERBOSE
447 fprintf(stderr," checking static...\n");
451 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
452 /* a static field is accessed via an instance, or vice versa */
453 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
454 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
455 : "instance field accessed without instance");
456 return false; /* exception */
459 /* for non-static accesses we have to check the constraints on the instance type */
460 if ((ref->flags & RESOLVE_STATIC) == 0) {
461 #ifdef RESOLVE_VERBOSE
462 fprintf(stderr," checking instance types...\n");
465 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
466 &(ref->instancetypes),
467 CLASSREF_OR_CLASSINFO(container),
470 resolveLinkageError,&checked))
472 return false; /* exception */
475 return true; /* be lazy */
478 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
480 /* for PUT* instructions we have to check the constraints on the value type */
481 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
482 RESOLVE_ASSERT(fieldtyperef);
483 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
484 /* check subtype constraints */
485 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
486 &(ref->valueconstraints),
487 CLASSREF_OR_CLASSINFO(fieldtyperef),
490 resolveLinkageError,&checked))
492 return false; /* exception */
495 return true; /* be lazy */
499 /* check access rights */
500 if (!is_accessible_member(referer,declarer,fi->flags)) {
501 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
502 "field is not accessible XXX add message");
503 return false; /* exception */
506 /* check protected access */
507 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
508 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
509 &(ref->instancetypes),
510 CLASSREF_OR_CLASSINFO(referer),
513 resolveIllegalAccessError,&checked))
515 return false; /* exception */
518 return true; /* be lazy */
521 /* impose loading constraint on field type */
522 if (fi->type == TYPE_ADR) {
523 RESOLVE_ASSERT(fieldtyperef);
524 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
526 return false; /* exception */
534 /******************************************************************************/
535 /* METHOD RESOLUTION */
536 /******************************************************************************/
538 /* for documentation see resolve.h */
540 resolve_method(unresolved_method *ref,
545 classinfo *container;
548 typedesc *paramtypes;
554 RESOLVE_ASSERT(result);
555 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
557 #ifdef RESOLVE_VERBOSE
558 unresolved_method_debug_dump(ref,stderr);
563 /* the class containing the reference */
564 referer = ref->methodref->classref->referer;
565 RESOLVE_ASSERT(referer);
567 /* first we must resolve the class containg the method */
568 if (!resolve_class(referer,ref->referermethod,
569 ref->methodref->classref->name,mode,&container))
571 /* the class reference could not be resolved */
572 return false; /* exception */
575 return true; /* be lazy */
577 RESOLVE_ASSERT(container);
579 /* now we must find the declaration of the method in `container`
580 * or one of its superclasses */
582 if ((container->flags & ACC_INTERFACE) != 0) {
583 mi = class_resolveinterfacemethod(container,
584 ref->methodref->name,ref->methodref->descriptor,
588 mi = class_resolveclassmethod(container,
589 ref->methodref->name,ref->methodref->descriptor,
593 return false; /* exception */ /* XXX set exceptionptr? */
595 /* { the method reference has been resolved } */
596 declarer = mi->class;
597 RESOLVE_ASSERT(declarer);
600 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
601 /* a static method is accessed via an instance, or vice versa */
602 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
603 (mi->flags & ACC_STATIC) ? "static method called via instance"
604 : "instance method called without instance");
605 return false; /* exception */
608 /* for non-static methods we have to check the constraints on the instance type */
609 if ((ref->flags & RESOLVE_STATIC) == 0) {
610 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
611 &(ref->instancetypes),
612 CLASSREF_OR_CLASSINFO(container),
615 resolveLinkageError,&checked))
617 return false; /* exception */
620 return true; /* be lazy */
627 /* check subtype constraints for TYPE_ADR parameters */
628 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
629 paramtypes = ref->methodref->parseddesc.md->paramtypes;
631 for (i=0; i<(mi->paramcount-instancecount); ++i) {
632 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
633 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
634 if (ref->paramconstraints) {
635 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
636 ref->paramconstraints + i,
637 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
640 resolveLinkageError,&checked))
642 return false; /* exception */
645 return true; /* be lazy */
650 /* check access rights */
651 if (!is_accessible_member(referer,declarer,mi->flags)) {
652 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
653 "method is not accessible XXX add message");
654 return false; /* exception */
657 /* check protected access */
658 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
659 /* XXX do we also need to check (referer subclass_of declarer)? */
660 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
661 &(ref->instancetypes),
662 CLASSREF_OR_CLASSINFO(referer),
665 resolveIllegalAccessError,&checked))
667 return false; /* exception */
670 return true; /* be lazy */
673 /* impose loading constraints on parameters (including instance) */
674 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
675 for (i=0; i<mi->paramcount; ++i) {
676 if (mi->paramtypes[i] == TYPE_ADR) {
679 if (i < instancecount)
680 name = container->name; /* XXX should this be declarer->name? */
682 name = paramtypes[i].classref->name;
684 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
685 return false; /* exception */
689 /* impose loading constraing onto return type */
690 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
691 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
692 ref->methodref->parseddesc.md->returntype.classref->name))
693 return false; /* exception */
701 /******************************************************************************/
702 /* CREATING THE DATA STRUCTURES */
703 /******************************************************************************/
706 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
707 unresolved_subtype_set *stset,typeinfo *tinfo,
708 constant_classref *declaredtype)
713 RESOLVE_ASSERT(stset);
714 RESOLVE_ASSERT(tinfo);
716 #ifdef RESOLVE_VERBOSE
717 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
718 #ifdef TYPEINFO_DEBUG
719 typeinfo_print(stderr,tinfo,4);
720 fprintf(stderr,"\n");
722 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
723 fprintf(stderr,"\n");
726 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
727 *exceptionptr = new_verifyerror(refmethod,
728 "Invalid use of returnAddress");
732 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
733 *exceptionptr = new_verifyerror(refmethod,
734 "Invalid use of uninitialized object");
738 /* the nulltype is always assignable (XXX for reversed?) */
739 if (TYPEINFO_IS_NULLTYPE(*tinfo))
742 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
743 if (declaredtype->name == utf_java_lang_Object
744 && referer->classloader == NULL)
750 count = tinfo->merged->count;
751 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
752 for (i=0; i<count; ++i) {
753 stset->subtyperefs[i] = tinfo->merged->list[i];
755 stset->subtyperefs[count].any = NULL; /* terminate */
758 if ((IS_CLASSREF(tinfo->typeclass)
759 ? tinfo->typeclass.ref->name
760 : tinfo->typeclass.cls->name) == declaredtype->name)
765 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
766 stset->subtyperefs[0] = tinfo->typeclass;
767 stset->subtyperefs[1].any = NULL; /* terminate */
774 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
779 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
783 unresolved_field *ref;
784 constant_FMIref *fieldref = NULL;
785 stackelement *instanceslot = NULL;
788 typeinfo *tip = NULL;
791 #ifdef RESOLVE_VERBOSE
792 fprintf(stderr,"create_unresolved_field\n");
793 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
794 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
795 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
798 ref = NEW(unresolved_field);
800 ref->referermethod = refmethod;
802 switch (iptr[0].opc) {
804 ref->flags |= RESOLVE_PUTFIELD;
805 instanceslot = stack->prev;
806 tip = &(stack->typeinfo);
807 fieldref = (constant_FMIref *) iptr[0].val.a;
810 case ICMD_PUTFIELDCONST:
811 ref->flags |= RESOLVE_PUTFIELD;
812 instanceslot = stack;
813 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
817 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
818 fieldref = (constant_FMIref *) iptr[0].val.a;
819 tip = &(stack->typeinfo);
822 case ICMD_PUTSTATICCONST:
823 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
824 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
828 instanceslot = stack;
829 fieldref = (constant_FMIref *) iptr[0].val.a;
833 ref->flags |= RESOLVE_STATIC;
834 fieldref = (constant_FMIref *) iptr[0].val.a;
838 RESOLVE_ASSERT(fieldref);
839 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
840 fd = fieldref->parseddesc.fd;
843 #ifdef RESOLVE_VERBOSE
844 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
845 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
846 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
847 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
849 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
852 ref->fieldref = fieldref;
854 /* record subtype constraints for the instance type, if any */
857 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
859 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
860 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
862 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
863 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
864 : refmethod->class; /* XXX classrefs */
865 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
866 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
870 insttip = &(instanceslot->typeinfo);
872 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
873 &(ref->instancetypes),insttip,fieldref->classref))
877 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
880 /* record subtype constraints for the value type, if any */
882 if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
884 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
886 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
887 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
890 TYPEINFO_INIT_NULLTYPE(tinfo);
892 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
893 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
897 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
904 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
908 unresolved_method *ref;
909 constant_FMIref *methodref;
910 stackelement *instanceslot = NULL;
917 methodref = (constant_FMIref *) iptr[0].val.a;
918 RESOLVE_ASSERT(methodref);
919 md = methodref->parseddesc.md;
922 #ifdef RESOLVE_VERBOSE
923 fprintf(stderr,"create_unresolved_method\n");
924 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
925 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
926 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
927 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
928 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
929 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
930 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
933 ref = NEW(unresolved_method);
935 ref->referermethod = refmethod;
936 ref->methodref = methodref;
937 ref->paramconstraints = NULL;
939 switch (iptr[0].opc) {
940 case ICMD_INVOKESTATIC:
941 ref->flags |= RESOLVE_STATIC;
943 case ICMD_INVOKEVIRTUAL:
944 case ICMD_INVOKESPECIAL:
945 case ICMD_INVOKEINTERFACE:
948 RESOLVE_ASSERT(false);
951 if ((ref->flags & RESOLVE_STATIC) == 0) {
952 /* find the instance slot under all the parameter slots on the stack */
953 instanceslot = stack;
954 for (i=0; i<md->paramcount; ++i)
955 instanceslot = instanceslot->prev;
958 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
960 /* record subtype constraints for the instance type, if any */
964 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
966 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
967 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
969 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
970 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
971 : refmethod->class; /* XXX classrefs */
972 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
973 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
977 tip = &(instanceslot->typeinfo);
979 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
980 &(ref->instancetypes),tip,methodref->classref))
984 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
987 /* record subtype constraints for the parameter types, if any */
989 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
990 type = md->paramtypes[i].type;
992 RESOLVE_ASSERT(param);
993 RESOLVE_ASSERT(type == param->type);
995 if (type == TYPE_ADR) {
996 if (!ref->paramconstraints) {
997 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
998 for (j=md->paramcount-1; j>i; --j)
999 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1001 RESOLVE_ASSERT(ref->paramconstraints);
1002 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1003 ref->paramconstraints + i,&(param->typeinfo),
1004 md->paramtypes[i].classref))
1008 if (ref->paramconstraints)
1009 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1016 /******************************************************************************/
1017 /* FREEING MEMORY */
1018 /******************************************************************************/
1021 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1024 classref_or_classinfo *p = list;
1026 /* this is silly. we *only* need to count the elements for MFREE */
1029 MFREE(list,classref_or_classinfo,(p - list));
1033 /* unresolved_field_free *******************************************************
1035 Free the memory used by an unresolved_field
1038 ref..............the unresolved_field
1040 *******************************************************************************/
1043 unresolved_field_free(unresolved_field *ref)
1045 RESOLVE_ASSERT(ref);
1047 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1048 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1049 FREE(ref,unresolved_field);
1052 /* unresolved_method_free ******************************************************
1054 Free the memory used by an unresolved_method
1057 ref..............the unresolved_method
1059 *******************************************************************************/
1062 unresolved_method_free(unresolved_method *ref)
1064 RESOLVE_ASSERT(ref);
1066 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1067 if (ref->paramconstraints) {
1069 int count = ref->methodref->parseddesc.md->paramcount;
1071 for (i=0; i<count; ++i)
1072 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1073 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1075 FREE(ref,unresolved_method);
1078 /******************************************************************************/
1080 /******************************************************************************/
1082 /* unresolved_subtype_set_debug_dump *******************************************
1084 Print debug info for unresolved_subtype_set to stream
1087 stset............the unresolved_subtype_set
1088 file.............the stream
1090 *******************************************************************************/
1093 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1095 classref_or_classinfo *p;
1097 if (SUBTYPESET_IS_EMPTY(*stset)) {
1098 fprintf(file," (empty)\n");
1101 p = stset->subtyperefs;
1102 for (;p->any; ++p) {
1103 if (IS_CLASSREF(*p)) {
1104 fprintf(file," ref: ");
1105 utf_fprint(file,p->ref->name);
1108 fprintf(file," cls: ");
1109 utf_fprint(file,p->cls->name);
1116 /* unresolved_field_debug_dump *************************************************
1118 Print debug info for unresolved_field to stream
1121 ref..............the unresolved_field
1122 file.............the stream
1124 *******************************************************************************/
1127 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1129 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1131 fprintf(file," referer : ");
1132 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1133 fprintf(file," refmethod : ");
1134 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1135 fprintf(file," refmethodd : ");
1136 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1137 fprintf(file," classname : ");
1138 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1139 fprintf(file," name : ");
1140 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1141 fprintf(file," descriptor: ");
1142 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1143 fprintf(file," parseddesc: ");
1144 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1145 fprintf(file," flags : %04x\n",ref->flags);
1146 fprintf(file," instancetypes:\n");
1147 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1148 fprintf(file," valueconstraints:\n");
1149 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1153 /* unresolved_method_debug_dump ************************************************
1155 Print debug info for unresolved_method to stream
1158 ref..............the unresolved_method
1159 file.............the stream
1161 *******************************************************************************/
1164 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1168 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1170 fprintf(file," referer : ");
1171 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1172 fprintf(file," refmethod : ");
1173 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1174 fprintf(file," refmethodd : ");
1175 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1176 fprintf(file," classname : ");
1177 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1178 fprintf(file," name : ");
1179 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1180 fprintf(file," descriptor: ");
1181 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1182 fprintf(file," parseddesc: ");
1183 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1184 fprintf(file," flags : %04x\n",ref->flags);
1185 fprintf(file," instancetypes:\n");
1186 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1187 fprintf(file," paramconstraints:\n");
1188 if (ref->paramconstraints) {
1189 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1190 fprintf(file," param %d:\n",i);
1191 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1195 fprintf(file," (empty)\n");
1201 * These are local overrides for various environment variables in Emacs.
1202 * Please do not remove this and leave it at the end of the file, where
1203 * Emacs will automagically detect them.
1204 * ---------------------------------------------------------------------
1207 * indent-tabs-mode: t
1211 * vim:noexpandtab:sw=4:ts=4: