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 2193 2005-04-02 19:33:43Z 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 if (!load_class_from_classloader(classname,referer->classloader,&cls))
140 return false; /* exception */
144 /* the class is now loaded */
146 RESOLVE_ASSERT(cls->loaded);
148 #ifdef RESOLVE_VERBOSE
149 fprintf(stderr," checking access rights...\n");
152 /* check access rights of referer to refered class */
153 if (!is_accessible_class(referer,cls)) {
154 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
155 "class is not accessible XXX add message");
156 return false; /* exception */
159 /* resolution succeeds */
160 #ifdef RESOLVE_VERBOSE
161 fprintf(stderr," success.\n");
168 resolve_classref(methodinfo *refmethod,
169 constant_classref *ref,
174 return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
178 resolve_classref_or_classinfo(methodinfo *refmethod,
179 classref_or_classinfo cls,
186 RESOLVE_ASSERT(cls.any);
187 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
188 RESOLVE_ASSERT(result);
192 if (IS_CLASSREF(cls)) {
193 /* we must resolve this reference */
194 if (!resolve_class(cls.ref->referer,refmethod,cls.ref->name,
196 return false; /* exception */
199 /* cls has already been resolved */
201 RESOLVE_ASSERT(c->loaded);
203 RESOLVE_ASSERT(c || (mode == resolveLazy));
206 return true; /* be lazy */
209 RESOLVE_ASSERT(c->loaded);
214 return false; /* exception */
215 RESOLVE_ASSERT(c->linked);
224 resolve_class_from_typedesc(typedesc *d,bool link,classinfo **result)
229 RESOLVE_ASSERT(result);
233 #ifdef RESOLVE_VERBOSE
234 fprintf(stderr,"resolve_class_from_typedesc(");
235 descriptor_debug_print_typedesc(stderr,d);
236 fprintf(stderr,",%i)\n",link);
240 /* a reference type */
241 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
242 resolveEager,link,&cls))
243 return false; /* exception */
246 /* a primitive type */
247 cls = primitivetype_table[d->decltype].class_primitive;
248 RESOLVE_ASSERT(cls->loaded);
250 if (!link_class(cls))
251 return false; /* exception */
254 RESOLVE_ASSERT(cls->loaded);
255 RESOLVE_ASSERT(!link || cls->linked);
257 #ifdef RESOLVE_VERBOSE
258 fprintf(stderr," result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
265 /******************************************************************************/
266 /* SUBTYPE SET CHECKS */
267 /******************************************************************************/
269 /* for documentation see resolve.h */
271 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
272 unresolved_subtype_set *ref,
273 classref_or_classinfo typeref,
279 classref_or_classinfo *setp;
285 RESOLVE_ASSERT(referer);
287 RESOLVE_ASSERT(typeref.any);
288 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
289 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
291 #ifdef RESOLVE_VERBOSE
292 fprintf(stderr,"resolve_and_check_subtype_set\n");
293 unresolved_subtype_set_debug_dump(ref,stderr);
294 if (IS_CLASSREF(typeref)) {
295 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
298 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
300 fprintf(stderr,"\n");
303 setp = ref->subtyperefs;
305 /* an empty set of tests always succeeds */
306 if (!setp || !setp->any) {
315 /* first resolve the type if necessary */
316 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
317 return false; /* exception */
319 return true; /* be lazy */
321 RESOLVE_ASSERT(type);
322 RESOLVE_ASSERT(type->loaded);
323 RESOLVE_ASSERT(type->linked);
324 TYPEINFO_INIT_CLASSINFO(typeti,type);
326 for (; setp->any; ++setp) {
327 /* first resolve the set member if necessary */
328 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
329 return false; /* exception */
331 return true; /* be lazy */
333 RESOLVE_ASSERT(result);
334 RESOLVE_ASSERT(result->loaded);
335 RESOLVE_ASSERT(result->linked);
337 #ifdef RESOLVE_VERBOSE
338 fprintf(stderr,"performing subclass test:\n");
339 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
340 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
341 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
344 /* now check the subtype relationship */
345 TYPEINFO_INIT_CLASSINFO(resultti,result);
347 /* we must test against `true` because `MAYBE` is also != 0 */
348 if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
349 #ifdef RESOLVE_VERBOSE
350 fprintf(stderr,"reversed subclass test failed\n");
356 /* we must test against `true` because `MAYBE` is also != 0 */
357 if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
358 #ifdef RESOLVE_VERBOSE
359 fprintf(stderr,"subclass test failed\n");
372 if (error == resolveIllegalAccessError)
373 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
374 "illegal access to protected member XXX add message");
376 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
377 "subtype constraint violated XXX add message");
378 return false; /* exception */
381 /******************************************************************************/
382 /* FIELD RESOLUTION */
383 /******************************************************************************/
385 /* for documentation see resolve.h */
387 resolve_field(unresolved_field *ref,
392 classinfo *container;
394 constant_classref *fieldtyperef;
399 RESOLVE_ASSERT(result);
400 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
404 #ifdef RESOLVE_VERBOSE
405 unresolved_field_debug_dump(ref,stderr);
408 /* the class containing the reference */
409 referer = ref->fieldref->classref->referer;
410 RESOLVE_ASSERT(referer);
412 /* first we must resolve the class containg the field */
413 if (!resolve_class(referer,ref->referermethod,
414 ref->fieldref->classref->name,mode,&container))
416 /* the class reference could not be resolved */
417 return false; /* exception */
420 return true; /* be lazy */
422 RESOLVE_ASSERT(container);
423 RESOLVE_ASSERT(container->loaded && container->linked);
425 /* now we must find the declaration of the field in `container`
426 * or one of its superclasses */
428 #ifdef RESOLVE_VERBOSE
429 fprintf(stderr," resolving field in class...\n");
432 fi = class_resolvefield(container,
433 ref->fieldref->name,ref->fieldref->descriptor,
436 return false; /* exception */
438 /* { the field reference has been resolved } */
439 declarer = fi->class;
440 RESOLVE_ASSERT(declarer);
441 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
443 #ifdef RESOLVE_VERBOSE
444 fprintf(stderr," checking static...\n");
448 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
449 /* a static field is accessed via an instance, or vice versa */
450 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
451 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
452 : "instance field accessed without instance");
453 return false; /* exception */
456 /* for non-static accesses we have to check the constraints on the instance type */
457 if ((ref->flags & RESOLVE_STATIC) == 0) {
458 #ifdef RESOLVE_VERBOSE
459 fprintf(stderr," checking instance types...\n");
462 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
463 &(ref->instancetypes),
464 CLASSREF_OR_CLASSINFO(container),
467 resolveLinkageError,&checked))
469 return false; /* exception */
472 return true; /* be lazy */
475 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
477 /* for PUT* instructions we have to check the constraints on the value type */
478 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
479 RESOLVE_ASSERT(fieldtyperef);
480 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
481 /* check subtype constraints */
482 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
483 &(ref->valueconstraints),
484 CLASSREF_OR_CLASSINFO(fieldtyperef),
487 resolveLinkageError,&checked))
489 return false; /* exception */
492 return true; /* be lazy */
496 /* check access rights */
497 if (!is_accessible_member(referer,declarer,fi->flags)) {
498 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
499 "field is not accessible XXX add message");
500 return false; /* exception */
503 /* check protected access */
504 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
505 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
506 &(ref->instancetypes),
507 CLASSREF_OR_CLASSINFO(referer),
510 resolveIllegalAccessError,&checked))
512 return false; /* exception */
515 return true; /* be lazy */
518 /* impose loading constraint on field type */
519 if (fi->type == TYPE_ADR) {
520 RESOLVE_ASSERT(fieldtyperef);
521 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
523 return false; /* exception */
531 /******************************************************************************/
532 /* METHOD RESOLUTION */
533 /******************************************************************************/
535 /* for documentation see resolve.h */
537 resolve_method(unresolved_method *ref,
542 classinfo *container;
545 typedesc *paramtypes;
551 RESOLVE_ASSERT(result);
552 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
554 #ifdef RESOLVE_VERBOSE
555 unresolved_method_debug_dump(ref,stderr);
560 /* the class containing the reference */
561 referer = ref->methodref->classref->referer;
562 RESOLVE_ASSERT(referer);
564 /* first we must resolve the class containg the method */
565 if (!resolve_class(referer,ref->referermethod,
566 ref->methodref->classref->name,mode,&container))
568 /* the class reference could not be resolved */
569 return false; /* exception */
572 return true; /* be lazy */
574 RESOLVE_ASSERT(container);
576 /* now we must find the declaration of the method in `container`
577 * or one of its superclasses */
579 if ((container->flags & ACC_INTERFACE) != 0) {
580 mi = class_resolveinterfacemethod(container,
581 ref->methodref->name,ref->methodref->descriptor,
585 mi = class_resolveclassmethod(container,
586 ref->methodref->name,ref->methodref->descriptor,
590 return false; /* exception */ /* XXX set exceptionptr? */
592 /* { the method reference has been resolved } */
593 declarer = mi->class;
594 RESOLVE_ASSERT(declarer);
597 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
598 /* a static method is accessed via an instance, or vice versa */
599 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
600 (mi->flags & ACC_STATIC) ? "static method called via instance"
601 : "instance method called without instance");
602 return false; /* exception */
605 /* for non-static methods we have to check the constraints on the instance type */
606 if ((ref->flags & RESOLVE_STATIC) == 0) {
607 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
608 &(ref->instancetypes),
609 CLASSREF_OR_CLASSINFO(container),
612 resolveLinkageError,&checked))
614 return false; /* exception */
617 return true; /* be lazy */
624 /* check subtype constraints for TYPE_ADR parameters */
625 RESOLVE_ASSERT((mi->paramcount-instancecount) == ref->methodref->parseddesc.md->paramcount);
626 paramtypes = ref->methodref->parseddesc.md->paramtypes;
628 for (i=0; i<(mi->paramcount-instancecount); ++i) {
629 if (mi->paramtypes[instancecount + i] == TYPE_ADR) {
630 RESOLVE_ASSERT(paramtypes[i].type == TYPE_ADR);
631 if (ref->paramconstraints) {
632 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
633 ref->paramconstraints + i,
634 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
637 resolveLinkageError,&checked))
639 return false; /* exception */
642 return true; /* be lazy */
647 /* check access rights */
648 if (!is_accessible_member(referer,declarer,mi->flags)) {
649 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
650 "method is not accessible XXX add message");
651 return false; /* exception */
654 /* check protected access */
655 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
656 /* XXX do we also need to check (referer subclass_of declarer)? */
657 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
658 &(ref->instancetypes),
659 CLASSREF_OR_CLASSINFO(referer),
662 resolveIllegalAccessError,&checked))
664 return false; /* exception */
667 return true; /* be lazy */
670 /* impose loading constraints on parameters (including instance) */
671 paramtypes = ref->methodref->parseddesc.md->paramtypes - instancecount;
672 for (i=0; i<mi->paramcount; ++i) {
673 if (mi->paramtypes[i] == TYPE_ADR) {
676 if (i < instancecount)
677 name = container->name; /* XXX should this be declarer->name? */
679 name = paramtypes[i].classref->name;
681 if (!classcache_add_constraint(referer->classloader,declarer->classloader,name))
682 return false; /* exception */
686 /* impose loading constraing onto return type */
687 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
688 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
689 ref->methodref->parseddesc.md->returntype.classref->name))
690 return false; /* exception */
698 /******************************************************************************/
699 /* CREATING THE DATA STRUCTURES */
700 /******************************************************************************/
703 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
704 unresolved_subtype_set *stset,typeinfo *tinfo,
705 constant_classref *declaredtype)
710 RESOLVE_ASSERT(stset);
711 RESOLVE_ASSERT(tinfo);
713 #ifdef RESOLVE_VERBOSE
714 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
715 #ifdef TYPEINFO_DEBUG
716 typeinfo_print(stderr,tinfo,4);
717 fprintf(stderr,"\n");
719 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
720 fprintf(stderr,"\n");
723 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
724 *exceptionptr = new_verifyerror(refmethod,
725 "Invalid use of returnAddress");
729 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
730 *exceptionptr = new_verifyerror(refmethod,
731 "Invalid use of uninitialized object");
735 /* the nulltype is always assignable (XXX for reversed?) */
736 if (TYPEINFO_IS_NULLTYPE(*tinfo))
739 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
740 if (declaredtype->name == utf_java_lang_Object
741 && referer->classloader == NULL)
747 count = tinfo->merged->count;
748 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
749 for (i=0; i<count; ++i) {
750 stset->subtyperefs[i] = tinfo->merged->list[i];
752 stset->subtyperefs[count].any = NULL; /* terminate */
755 if ((IS_CLASSREF(tinfo->typeclass)
756 ? tinfo->typeclass.ref->name
757 : tinfo->typeclass.cls->name) == declaredtype->name)
762 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
763 stset->subtyperefs[0] = tinfo->typeclass;
764 stset->subtyperefs[1].any = NULL; /* terminate */
771 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
776 create_unresolved_field(classinfo *referer,methodinfo *refmethod,
780 unresolved_field *ref;
781 constant_FMIref *fieldref = NULL;
782 stackelement *instanceslot = NULL;
785 typeinfo *tip = NULL;
788 #ifdef RESOLVE_VERBOSE
789 fprintf(stderr,"create_unresolved_field\n");
790 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
791 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
792 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
795 ref = NEW(unresolved_field);
797 ref->referermethod = refmethod;
799 switch (iptr[0].opc) {
801 ref->flags |= RESOLVE_PUTFIELD;
802 instanceslot = stack->prev;
803 tip = &(stack->typeinfo);
804 fieldref = (constant_FMIref *) iptr[0].val.a;
807 case ICMD_PUTFIELDCONST:
808 ref->flags |= RESOLVE_PUTFIELD;
809 instanceslot = stack;
810 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
814 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
815 fieldref = (constant_FMIref *) iptr[0].val.a;
816 tip = &(stack->typeinfo);
819 case ICMD_PUTSTATICCONST:
820 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
821 fieldref = INSTRUCTION_PUTCONST_FIELDREF(iptr);
825 instanceslot = stack;
826 fieldref = (constant_FMIref *) iptr[0].val.a;
830 ref->flags |= RESOLVE_STATIC;
831 fieldref = (constant_FMIref *) iptr[0].val.a;
835 RESOLVE_ASSERT(fieldref);
836 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
837 fd = fieldref->parseddesc.fd;
840 #ifdef RESOLVE_VERBOSE
841 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
842 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
843 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
844 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
846 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
849 ref->fieldref = fieldref;
851 /* record subtype constraints for the instance type, if any */
854 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
856 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
857 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
859 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
860 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
861 : refmethod->class; /* XXX classrefs */
862 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
863 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
867 insttip = &(instanceslot->typeinfo);
869 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
870 &(ref->instancetypes),insttip,fieldref->classref))
874 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
877 /* record subtype constraints for the value type, if any */
879 if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
881 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
883 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
884 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String); /* XXX assert loaded & linked? */
887 TYPEINFO_INIT_NULLTYPE(tinfo);
889 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
890 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
894 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
901 create_unresolved_method(classinfo *referer,methodinfo *refmethod,
905 unresolved_method *ref;
906 constant_FMIref *methodref;
907 stackelement *instanceslot = NULL;
914 methodref = (constant_FMIref *) iptr[0].val.a;
915 RESOLVE_ASSERT(methodref);
916 md = methodref->parseddesc.md;
919 #ifdef RESOLVE_VERBOSE
920 fprintf(stderr,"create_unresolved_method\n");
921 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
922 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
923 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
924 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
925 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
926 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
927 fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);
930 ref = NEW(unresolved_method);
932 ref->referermethod = refmethod;
933 ref->methodref = methodref;
934 ref->paramconstraints = NULL;
936 switch (iptr[0].opc) {
937 case ICMD_INVOKESTATIC:
938 ref->flags |= RESOLVE_STATIC;
940 case ICMD_INVOKEVIRTUAL:
941 case ICMD_INVOKESPECIAL:
942 case ICMD_INVOKEINTERFACE:
945 RESOLVE_ASSERT(false);
948 if ((ref->flags & RESOLVE_STATIC) == 0) {
949 /* find the instance slot under all the parameter slots on the stack */
950 instanceslot = stack;
951 for (i=0; i<md->paramcount; ++i)
952 instanceslot = instanceslot->prev;
955 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
957 /* record subtype constraints for the instance type, if any */
961 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
963 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
964 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
966 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
967 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
968 : refmethod->class; /* XXX classrefs */
969 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
970 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
974 tip = &(instanceslot->typeinfo);
976 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
977 &(ref->instancetypes),tip,methodref->classref))
981 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
984 /* record subtype constraints for the parameter types, if any */
986 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
987 type = md->paramtypes[i].type;
989 RESOLVE_ASSERT(param);
990 RESOLVE_ASSERT(type == param->type);
992 if (type == TYPE_ADR) {
993 if (!ref->paramconstraints) {
994 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
995 for (j=md->paramcount-1; j>i; --j)
996 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
998 RESOLVE_ASSERT(ref->paramconstraints);
999 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1000 ref->paramconstraints + i,&(param->typeinfo),
1001 md->paramtypes[i].classref))
1005 if (ref->paramconstraints)
1006 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1013 /******************************************************************************/
1014 /* FREEING MEMORY */
1015 /******************************************************************************/
1018 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1021 classref_or_classinfo *p = list;
1023 /* this is silly. we *only* need to count the elements for MFREE */
1026 MFREE(list,classref_or_classinfo,(p - list));
1030 /* unresolved_field_free *******************************************************
1032 Free the memory used by an unresolved_field
1035 ref..............the unresolved_field
1037 *******************************************************************************/
1040 unresolved_field_free(unresolved_field *ref)
1042 RESOLVE_ASSERT(ref);
1044 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1045 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1046 FREE(ref,unresolved_field);
1049 /* unresolved_method_free ******************************************************
1051 Free the memory used by an unresolved_method
1054 ref..............the unresolved_method
1056 *******************************************************************************/
1059 unresolved_method_free(unresolved_method *ref)
1061 RESOLVE_ASSERT(ref);
1063 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1064 if (ref->paramconstraints) {
1066 int count = ref->methodref->parseddesc.md->paramcount;
1068 for (i=0; i<count; ++i)
1069 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1070 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1072 FREE(ref,unresolved_method);
1075 /******************************************************************************/
1077 /******************************************************************************/
1079 /* unresolved_subtype_set_debug_dump *******************************************
1081 Print debug info for unresolved_subtype_set to stream
1084 stset............the unresolved_subtype_set
1085 file.............the stream
1087 *******************************************************************************/
1090 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1092 classref_or_classinfo *p;
1094 if (SUBTYPESET_IS_EMPTY(*stset)) {
1095 fprintf(file," (empty)\n");
1098 p = stset->subtyperefs;
1099 for (;p->any; ++p) {
1100 if (IS_CLASSREF(*p)) {
1101 fprintf(file," ref: ");
1102 utf_fprint(file,p->ref->name);
1105 fprintf(file," cls: ");
1106 utf_fprint(file,p->cls->name);
1113 /* unresolved_field_debug_dump *************************************************
1115 Print debug info for unresolved_field to stream
1118 ref..............the unresolved_field
1119 file.............the stream
1121 *******************************************************************************/
1124 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1126 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1128 fprintf(file," referer : ");
1129 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1130 fprintf(file," refmethod : ");
1131 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1132 fprintf(file," refmethodd : ");
1133 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1134 fprintf(file," classname : ");
1135 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1136 fprintf(file," name : ");
1137 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1138 fprintf(file," descriptor: ");
1139 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1140 fprintf(file," parseddesc: ");
1141 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1142 fprintf(file," flags : %04x\n",ref->flags);
1143 fprintf(file," instancetypes:\n");
1144 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1145 fprintf(file," valueconstraints:\n");
1146 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1150 /* unresolved_method_debug_dump ************************************************
1152 Print debug info for unresolved_method to stream
1155 ref..............the unresolved_method
1156 file.............the stream
1158 *******************************************************************************/
1161 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1165 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1167 fprintf(file," referer : ");
1168 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1169 fprintf(file," refmethod : ");
1170 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1171 fprintf(file," refmethodd : ");
1172 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1173 fprintf(file," classname : ");
1174 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1175 fprintf(file," name : ");
1176 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1177 fprintf(file," descriptor: ");
1178 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1179 fprintf(file," parseddesc: ");
1180 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1181 fprintf(file," flags : %04x\n",ref->flags);
1182 fprintf(file," instancetypes:\n");
1183 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1184 fprintf(file," paramconstraints:\n");
1185 if (ref->paramconstraints) {
1186 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1187 fprintf(file," param %d:\n",i);
1188 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1192 fprintf(file," (empty)\n");
1198 * These are local overrides for various environment variables in Emacs.
1199 * Please do not remove this and leave it at the end of the file, where
1200 * Emacs will automagically detect them.
1201 * ---------------------------------------------------------------------
1204 * indent-tabs-mode: t
1208 * vim:noexpandtab:sw=4:ts=4: