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
29 Changes: Christan Thalinger
31 $Id: resolve.c 2738 2005-06-18 16:37:34Z edwin $
38 #include "mm/memory.h"
39 #include "vm/resolve.h"
40 #include "vm/access.h"
41 #include "vm/classcache.h"
42 #include "vm/descriptor.h"
43 #include "vm/exceptions.h"
44 #include "vm/linker.h"
45 #include "vm/loader.h"
46 #include "vm/stringlocal.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_from_name(classinfo *referer,methodinfo *refmethod,
79 classinfo *cls = NULL;
83 RESOLVE_ASSERT(result);
84 RESOLVE_ASSERT(referer);
85 RESOLVE_ASSERT(classname);
86 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
90 #ifdef RESOLVE_VERBOSE
91 fprintf(stderr,"resolve_class_from_name(");
92 utf_fprint(stderr,referer->name);
94 utf_fprint(stderr,classname);
95 fprintf(stderr,")\n");
98 /* lookup if this class has already been loaded */
99 cls = classcache_lookup(referer->classloader,classname);
101 #ifdef RESOLVE_VERBOSE
102 fprintf(stderr," lookup result: %p\n",(void*)cls);
106 /* resolve array types */
107 if (classname->text[0] == '[') {
108 utf_ptr = classname->text + 1;
109 len = classname->blength - 1;
110 /* classname is an array type name */
117 /* the component type is a reference type */
118 /* resolve the component type */
119 if (!resolve_class_from_name(referer,refmethod,
120 utf_new(utf_ptr,len),
122 return false; /* exception */
124 RESOLVE_ASSERT(mode == resolveLazy);
125 return true; /* be lazy */
127 /* create the array class */
128 cls = class_array_of(cls,false);
130 return false; /* exception */
134 /* the class has not been loaded, yet */
135 if (mode == resolveLazy)
136 return true; /* be lazy */
139 #ifdef RESOLVE_VERBOSE
140 fprintf(stderr," loading...\n");
145 if (!(cls = load_class_from_classloader(classname,
146 referer->classloader)))
147 return false; /* exception */
151 /* the class is now loaded */
153 RESOLVE_ASSERT(cls->loaded);
155 #ifdef RESOLVE_VERBOSE
156 fprintf(stderr," checking access rights...\n");
159 /* check access rights of referer to refered class */
160 if (!is_accessible_class(referer,cls)) {
161 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
162 "class is not accessible XXX add message");
163 return false; /* exception */
166 /* link the class if necessary */
169 if (!link_class(cls))
170 return false; /* exception */
171 RESOLVE_ASSERT(cls->linked);
174 /* resolution succeeds */
175 #ifdef RESOLVE_VERBOSE
176 fprintf(stderr," success.\n");
183 resolve_classref(methodinfo *refmethod,
184 constant_classref *ref,
189 return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,link,result);
193 resolve_classref_or_classinfo(methodinfo *refmethod,
194 classref_or_classinfo cls,
201 RESOLVE_ASSERT(cls.any);
202 RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
203 RESOLVE_ASSERT(result);
205 #ifdef RESOLVE_VERBOSE
206 fprintf(stderr,"resolve_classref_or_classinfo(");
207 utf_fprint(stderr,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
208 fprintf(stderr,",%i,%i)\n",mode,link);
213 if (IS_CLASSREF(cls)) {
214 /* we must resolve this reference */
215 if (!resolve_class_from_name(cls.ref->referer,refmethod,cls.ref->name,
217 return false; /* exception */
220 /* cls has already been resolved */
222 RESOLVE_ASSERT(c->loaded);
224 RESOLVE_ASSERT(c || (mode == resolveLazy));
227 return true; /* be lazy */
230 RESOLVE_ASSERT(c->loaded);
235 return false; /* exception */
236 RESOLVE_ASSERT(c->linked);
245 resolve_class_from_typedesc(typedesc *d, bool link, classinfo **result)
250 RESOLVE_ASSERT(result);
254 #ifdef RESOLVE_VERBOSE
255 fprintf(stderr,"resolve_class_from_typedesc(");
256 descriptor_debug_print_typedesc(stderr,d);
257 fprintf(stderr,",%i)\n",link);
261 /* a reference type */
262 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
263 resolveEager,link,&cls))
264 return false; /* exception */
267 /* a primitive type */
268 cls = primitivetype_table[d->decltype].class_primitive;
269 RESOLVE_ASSERT(cls->loaded);
271 if (!link_class(cls))
272 return false; /* exception */
275 RESOLVE_ASSERT(cls->loaded);
276 RESOLVE_ASSERT(!link || cls->linked);
278 #ifdef RESOLVE_VERBOSE
279 fprintf(stderr," result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
286 /******************************************************************************/
287 /* SUBTYPE SET CHECKS */
288 /******************************************************************************/
290 /* for documentation see resolve.h */
292 resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
293 unresolved_subtype_set *ref,
294 classref_or_classinfo typeref,
300 classref_or_classinfo *setp;
306 RESOLVE_ASSERT(referer);
308 RESOLVE_ASSERT(typeref.any);
309 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
310 RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
312 #ifdef RESOLVE_VERBOSE
313 fprintf(stderr,"resolve_and_check_subtype_set\n");
314 unresolved_subtype_set_debug_dump(ref,stderr);
315 if (IS_CLASSREF(typeref)) {
316 fprintf(stderr," ref: ");utf_fprint(stderr,typeref.ref->name);
319 fprintf(stderr," cls: ");utf_fprint(stderr,typeref.cls->name);
321 fprintf(stderr,"\n");
324 setp = ref->subtyperefs;
326 /* an empty set of tests always succeeds */
327 if (!setp || !setp->any) {
336 /* first resolve the type if necessary */
337 if (!resolve_classref_or_classinfo(refmethod,typeref,mode,true,&type))
338 return false; /* exception */
340 return true; /* be lazy */
342 RESOLVE_ASSERT(type);
343 RESOLVE_ASSERT(type->loaded);
344 RESOLVE_ASSERT(type->linked);
345 TYPEINFO_INIT_CLASSINFO(typeti,type);
347 for (; setp->any; ++setp) {
348 /* first resolve the set member if necessary */
349 if (!resolve_classref_or_classinfo(refmethod,*setp,mode,true,&result))
350 return false; /* exception */
352 return true; /* be lazy */
354 RESOLVE_ASSERT(result);
355 RESOLVE_ASSERT(result->loaded);
356 RESOLVE_ASSERT(result->linked);
358 #ifdef RESOLVE_VERBOSE
359 fprintf(stderr,"performing subclass test:\n");
360 fprintf(stderr," ");utf_fprint(stderr,result->name);fputc('\n',stderr);
361 fprintf(stderr," must be a %s of\n",(reversed) ? "superclass" : "subclass");
362 fprintf(stderr," ");utf_fprint(stderr,type->name);fputc('\n',stderr);
365 /* now check the subtype relationship */
366 TYPEINFO_INIT_CLASSINFO(resultti,result);
368 /* we must test against `true` because `MAYBE` is also != 0 */
369 if (true != typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result))) {
370 #ifdef RESOLVE_VERBOSE
371 fprintf(stderr,"reversed subclass test failed\n");
377 /* we must test against `true` because `MAYBE` is also != 0 */
378 if (true != typeinfo_is_assignable_to_class(&resultti,CLASSREF_OR_CLASSINFO(type))) {
379 #ifdef RESOLVE_VERBOSE
380 fprintf(stderr,"subclass test failed\n");
393 if (error == resolveIllegalAccessError)
394 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
395 "illegal access to protected member XXX add message");
397 *exceptionptr = new_exception_message(string_java_lang_LinkageError,
398 "subtype constraint violated XXX add message");
399 return false; /* exception */
402 /******************************************************************************/
403 /* CLASS RESOLUTION */
404 /******************************************************************************/
406 /* for documentation see resolve.h */
408 resolve_class(unresolved_class *ref,
416 RESOLVE_ASSERT(result);
417 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
421 #ifdef RESOLVE_VERBOSE
422 unresolved_class_debug_dump(ref,stderr);
425 /* first we must resolve the class */
426 if (!resolve_classref(ref->referermethod,
427 ref->classref,mode,true,&cls))
429 /* the class reference could not be resolved */
430 return false; /* exception */
433 return true; /* be lazy */
436 RESOLVE_ASSERT(cls->loaded && cls->linked);
438 /* now we check the subtype constraints */
439 if (!resolve_and_check_subtype_set(ref->classref->referer,ref->referermethod,
440 &(ref->subtypeconstraints),
441 CLASSREF_OR_CLASSINFO(cls),
444 resolveLinkageError,&checked))
446 return false; /* exception */
449 return true; /* be lazy */
456 /******************************************************************************/
457 /* FIELD RESOLUTION */
458 /******************************************************************************/
460 /* for documentation see resolve.h */
462 resolve_field(unresolved_field *ref,
467 classinfo *container;
469 constant_classref *fieldtyperef;
474 RESOLVE_ASSERT(result);
475 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
479 #ifdef RESOLVE_VERBOSE
480 unresolved_field_debug_dump(ref,stderr);
483 /* the class containing the reference */
484 referer = ref->fieldref->classref->referer;
485 RESOLVE_ASSERT(referer);
487 /* first we must resolve the class containg the field */
488 if (!resolve_class_from_name(referer,ref->referermethod,
489 ref->fieldref->classref->name,mode,true,&container))
491 /* the class reference could not be resolved */
492 return false; /* exception */
495 return true; /* be lazy */
497 RESOLVE_ASSERT(container);
498 RESOLVE_ASSERT(container->loaded && container->linked);
500 /* now we must find the declaration of the field in `container`
501 * or one of its superclasses */
503 #ifdef RESOLVE_VERBOSE
504 fprintf(stderr," resolving field in class...\n");
507 fi = class_resolvefield(container,
508 ref->fieldref->name,ref->fieldref->descriptor,
511 return false; /* exception */
513 /* { the field reference has been resolved } */
514 declarer = fi->class;
515 RESOLVE_ASSERT(declarer);
516 RESOLVE_ASSERT(declarer->loaded && declarer->linked);
518 #ifdef RESOLVE_VERBOSE
519 fprintf(stderr," checking static...\n");
523 if (((fi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) {
524 /* a static field is accessed via an instance, or vice versa */
525 *exceptionptr = new_exception_message(string_java_lang_IncompatibleClassChangeError,
526 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
527 : "instance field accessed without instance");
528 return false; /* exception */
531 /* for non-static accesses we have to check the constraints on the instance type */
532 if ((ref->flags & RESOLVE_STATIC) == 0) {
533 #ifdef RESOLVE_VERBOSE
534 fprintf(stderr," checking instance types...\n");
537 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
538 &(ref->instancetypes),
539 CLASSREF_OR_CLASSINFO(container),
542 resolveLinkageError,&checked))
544 return false; /* exception */
547 return true; /* be lazy */
550 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
552 /* for PUT* instructions we have to check the constraints on the value type */
553 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
554 RESOLVE_ASSERT(fieldtyperef);
555 if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
556 /* check subtype constraints */
557 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
558 &(ref->valueconstraints),
559 CLASSREF_OR_CLASSINFO(fieldtyperef),
562 resolveLinkageError,&checked))
564 return false; /* exception */
567 return true; /* be lazy */
571 /* check access rights */
572 if (!is_accessible_member(referer,declarer,fi->flags)) {
573 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
574 "field is not accessible XXX add message");
575 return false; /* exception */
578 /* check protected access */
579 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
580 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
581 &(ref->instancetypes),
582 CLASSREF_OR_CLASSINFO(referer),
585 resolveIllegalAccessError,&checked))
587 return false; /* exception */
590 return true; /* be lazy */
593 /* impose loading constraint on field type */
594 if (fi->type == TYPE_ADR) {
595 RESOLVE_ASSERT(fieldtyperef);
596 if (!classcache_add_constraint(declarer->classloader,referer->classloader,
598 return false; /* exception */
606 /******************************************************************************/
607 /* METHOD RESOLUTION */
608 /******************************************************************************/
610 /* for documentation see resolve.h */
612 resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
615 classinfo *container;
618 typedesc *paramtypes;
624 RESOLVE_ASSERT(result);
625 RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
627 #ifdef RESOLVE_VERBOSE
628 unresolved_method_debug_dump(ref,stderr);
633 /* the class containing the reference */
634 referer = ref->methodref->classref->referer;
635 RESOLVE_ASSERT(referer);
637 /* first we must resolve the class containg the method */
638 if (!resolve_class_from_name(referer,ref->referermethod,
639 ref->methodref->classref->name,mode,true,&container))
641 /* the class reference could not be resolved */
642 return false; /* exception */
645 return true; /* be lazy */
647 RESOLVE_ASSERT(container);
649 /* now we must find the declaration of the method in `container`
650 * or one of its superclasses */
652 if (container->flags & ACC_INTERFACE) {
653 mi = class_resolveinterfacemethod(container,
654 ref->methodref->name,
655 ref->methodref->descriptor,
659 mi = class_resolveclassmethod(container,
660 ref->methodref->name,
661 ref->methodref->descriptor,
666 return false; /* exception */ /* XXX set exceptionptr? */
668 /* { the method reference has been resolved } */
670 declarer = mi->class;
671 RESOLVE_ASSERT(declarer);
675 if (((mi->flags & ACC_STATIC) != 0) != ((ref->flags & RESOLVE_STATIC) != 0)) { /* a static method is accessed via an instance, or vice versa */
677 new_exception_message(string_java_lang_IncompatibleClassChangeError,
678 (mi->flags & ACC_STATIC) ? "static method called via instance"
679 : "instance method called without instance");
683 /* have the method params already been parsed? no, do it. */
685 if (!mi->parseddesc->params)
686 if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
689 /* for non-static methods we have to check the constraints on the */
692 if (!(ref->flags & RESOLVE_STATIC)) {
693 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
694 &(ref->instancetypes),
695 CLASSREF_OR_CLASSINFO(container),
698 resolveLinkageError,&checked))
700 return false; /* exception */
703 return true; /* be lazy */
710 /* check subtype constraints for TYPE_ADR parameters */
712 RESOLVE_ASSERT(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
713 paramtypes = mi->parseddesc->paramtypes;
715 for (i = 0; i < mi->parseddesc->paramcount; i++) {
716 if (paramtypes[i].type == TYPE_ADR) {
717 if (ref->paramconstraints) {
718 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
719 ref->paramconstraints + i,
720 CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
723 resolveLinkageError,&checked))
725 return false; /* exception */
728 return true; /* be lazy */
733 /* check access rights */
735 if (!is_accessible_member(referer,declarer,mi->flags)) {
736 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,
737 "method is not accessible XXX add message");
738 return false; /* exception */
741 /* check protected access */
743 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
744 if (!resolve_and_check_subtype_set(referer,ref->referermethod,
745 &(ref->instancetypes),
746 CLASSREF_OR_CLASSINFO(referer),
749 resolveIllegalAccessError,&checked))
751 return false; /* exception */
754 return true; /* be lazy */
757 /* impose loading constraints on parameters (including instance) */
759 paramtypes = mi->parseddesc->paramtypes;
761 for (i = 0; i < mi->parseddesc->paramcount; i++) {
762 if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
765 if (i < instancecount)
766 name = container->name; /* XXX should this be declarer->name? */
768 name = paramtypes[i].classref->name;
770 if (!classcache_add_constraint(referer->classloader,
771 declarer->classloader, name))
772 return false; /* exception */
776 /* impose loading constraing onto return type */
778 if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
779 if (!classcache_add_constraint(referer->classloader,declarer->classloader,
780 ref->methodref->parseddesc.md->returntype.classref->name))
781 return false; /* exception */
789 /******************************************************************************/
790 /* CREATING THE DATA STRUCTURES */
791 /******************************************************************************/
794 unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
795 unresolved_subtype_set *stset,typeinfo *tinfo,
796 constant_classref *declaredtype)
801 RESOLVE_ASSERT(stset);
802 RESOLVE_ASSERT(tinfo);
804 #ifdef RESOLVE_VERBOSE
805 fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
806 #ifdef TYPEINFO_DEBUG
807 /*typeinfo_print(stderr,tinfo,4);*/
808 fprintf(stderr,"\n");
810 fprintf(stderr," declared type:");utf_fprint(stderr,declaredtype->name);
811 fprintf(stderr,"\n");
814 if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
815 *exceptionptr = new_verifyerror(refmethod,
816 "Invalid use of returnAddress");
820 if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
821 *exceptionptr = new_verifyerror(refmethod,
822 "Invalid use of uninitialized object");
826 /* the nulltype is always assignable (XXX for reversed?) */
827 if (TYPEINFO_IS_NULLTYPE(*tinfo))
830 /* every type is assignable to (BOOTSTRAP)java.lang.Object */
831 if (declaredtype->name == utf_java_lang_Object
832 && referer->classloader == NULL)
838 count = tinfo->merged->count;
839 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
840 for (i=0; i<count; ++i) {
841 stset->subtyperefs[i] = tinfo->merged->list[i];
843 stset->subtyperefs[count].any = NULL; /* terminate */
846 if ((IS_CLASSREF(tinfo->typeclass)
847 ? tinfo->typeclass.ref->name
848 : tinfo->typeclass.cls->name) == declaredtype->name)
853 stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
854 stset->subtyperefs[0] = tinfo->typeclass;
855 stset->subtyperefs[1].any = NULL; /* terminate */
862 UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
866 /* create_unresolved_class *****************************************************
868 Create an unresolved_class struct for the given class reference
871 refmethod........the method triggering the resolution (if any)
872 classref.........the class reference
873 valuetype........value type to check against the resolved class
874 may be NULL, if no typeinfo is available
877 a pointer to a new unresolved_class struct, or
878 NULL if an exception has been thrown
880 *******************************************************************************/
883 create_unresolved_class(methodinfo *refmethod,
884 constant_classref *classref,
887 unresolved_class *ref;
891 #ifdef RESOLVE_VERBOSE
892 fprintf(stderr,"create_unresolved_class\n");
893 fprintf(stderr," referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
895 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
896 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
898 fprintf(stderr," name : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
901 ref = NEW(unresolved_class);
902 ref->classref = classref;
903 ref->referermethod = refmethod;
906 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
907 &(ref->subtypeconstraints),valuetype,classref))
911 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
917 /* create_unresolved_field *****************************************************
919 Create an unresolved_field struct for the given field access instruction
922 referer..........the class containing the reference
923 refmethod........the method triggering the resolution (if any)
924 iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
927 a pointer to a new unresolved_field struct, or
928 NULL if an exception has been thrown
930 *******************************************************************************/
933 create_unresolved_field(classinfo *referer, methodinfo *refmethod,
936 unresolved_field *ref;
937 constant_FMIref *fieldref = NULL;
939 #ifdef RESOLVE_VERBOSE
940 fprintf(stderr,"create_unresolved_field\n");
941 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
942 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
943 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
946 ref = NEW(unresolved_field);
948 ref->referermethod = refmethod;
949 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
951 switch (iptr[0].opc) {
953 ref->flags |= RESOLVE_PUTFIELD;
954 fieldref = (constant_FMIref *) iptr[0].val.a;
957 case ICMD_PUTFIELDCONST:
958 ref->flags |= RESOLVE_PUTFIELD;
959 fieldref = (constant_FMIref *) iptr[1].val.a;
963 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
964 fieldref = (constant_FMIref *) iptr[0].val.a;
967 case ICMD_PUTSTATICCONST:
968 ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
969 fieldref = (constant_FMIref *) iptr[1].val.a;
973 fieldref = (constant_FMIref *) iptr[0].val.a;
977 ref->flags |= RESOLVE_STATIC;
978 fieldref = (constant_FMIref *) iptr[0].val.a;
982 RESOLVE_ASSERT(fieldref);
984 #ifdef RESOLVE_VERBOSE
985 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
986 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
987 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
988 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
990 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
993 ref->fieldref = fieldref;
998 /* constrain_unresolved_field **************************************************
1000 Record subtype constraints for a field access.
1003 ref..............the unresolved_field structure of the access
1004 referer..........the class containing the reference
1005 refmethod........the method triggering the resolution (if any)
1006 iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
1007 stack............the input stack of the instruction
1010 true.............everything ok
1011 false............an exception has been thrown
1013 *******************************************************************************/
1016 constrain_unresolved_field(unresolved_field *ref,
1017 classinfo *referer, methodinfo *refmethod,
1019 stackelement *stack)
1021 unresolved_field *ref;
1022 constant_FMIref *fieldref;
1023 stackelement *instanceslot = NULL;
1026 typeinfo *tip = NULL;
1029 RESOLVE_ASSERT(ref);
1030 RESOLVE_ASSERT(stack);
1032 fieldref = ref->fieldref;
1033 RESOLVE_ASSERT(fieldref);
1035 #ifdef RESOLVE_VERBOSE
1036 fprintf(stderr,"constrain_unresolved_field\n");
1037 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1038 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1039 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1042 switch (iptr[0].opc) {
1044 instanceslot = stack->prev;
1045 tip = &(stack->typeinfo);
1048 case ICMD_PUTFIELDCONST:
1049 instanceslot = stack;
1052 case ICMD_PUTSTATIC:
1053 tip = &(stack->typeinfo);
1057 instanceslot = stack;
1061 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1062 fd = fieldref->parseddesc.fd;
1065 #ifdef RESOLVE_VERBOSE
1066 fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
1067 fprintf(stderr," name : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
1068 fprintf(stderr," desc : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
1069 fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
1071 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1074 /* record subtype constraints for the instance type, if any */
1077 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
1079 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
1080 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1081 { /* XXX clean up */
1082 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1083 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
1084 : refmethod->class; /* XXX classrefs */
1085 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
1086 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1090 insttip = &(instanceslot->typeinfo);
1092 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1093 &(ref->instancetypes),insttip,fieldref->classref))
1097 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1100 /* record subtype constraints for the value type, if any */
1102 if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
1104 /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
1106 if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
1107 RESOLVE_ASSERT(class_java_lang_String);
1108 RESOLVE_ASSERT(class_java_lang_String->loaded);
1109 RESOLVE_ASSERT(class_java_lang_String->linked);
1110 TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
1113 TYPEINFO_INIT_NULLTYPE(tinfo);
1115 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1116 &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
1120 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
1126 /* create_unresolved_method ****************************************************
1128 Create an unresolved_method struct for the given method invocation
1131 referer..........the class containing the reference
1132 refmethod........the method triggering the resolution (if any)
1133 iptr.............the INVOKE* instruction
1136 a pointer to a new unresolved_method struct, or
1137 NULL if an exception has been thrown
1139 *******************************************************************************/
1142 create_unresolved_method(classinfo *referer, methodinfo *refmethod,
1145 unresolved_method *ref;
1146 constant_FMIref *methodref;
1148 methodref = (constant_FMIref *) iptr[0].val.a;
1149 RESOLVE_ASSERT(methodref);
1151 #ifdef RESOLVE_VERBOSE
1152 fprintf(stderr,"create_unresolved_method\n");
1153 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1154 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1155 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1156 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1157 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1158 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1159 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1162 ref = NEW(unresolved_method);
1164 ref->referermethod = refmethod;
1165 ref->methodref = methodref;
1166 ref->paramconstraints = NULL;
1167 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
1169 switch (iptr[0].opc) {
1170 case ICMD_INVOKESTATIC:
1171 ref->flags |= RESOLVE_STATIC;
1173 case ICMD_INVOKEVIRTUAL:
1174 case ICMD_INVOKESPECIAL:
1175 case ICMD_INVOKEINTERFACE:
1178 RESOLVE_ASSERT(false);
1184 /* constrain_unresolved_method *************************************************
1186 Record subtype constraints for the arguments of a method call.
1189 ref..............the unresolved_method structure of the call
1190 referer..........the class containing the reference
1191 refmethod........the method triggering the resolution (if any)
1192 iptr.............the INVOKE* instruction
1193 stack............the input stack of the instruction
1196 true.............everything ok
1197 false............an exception has been thrown
1199 *******************************************************************************/
1202 constrain_unresolved_method(unresolved_method *ref,
1203 classinfo *referer, methodinfo *refmethod,
1205 stackelement *stack)
1207 constant_FMIref *methodref;
1208 stackelement *instanceslot = NULL;
1209 stackelement *param;
1215 RESOLVE_ASSERT(ref);
1216 RESOLVE_ASSERT(stack);
1217 methodref = ref->methodref;
1218 RESOLVE_ASSERT(methodref);
1219 md = methodref->parseddesc.md;
1222 #ifdef RESOLVE_VERBOSE
1223 fprintf(stderr,"constrain_unresolved_method\n");
1224 fprintf(stderr," referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
1225 fprintf(stderr," rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
1226 fprintf(stderr," rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
1227 fprintf(stderr," class : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
1228 fprintf(stderr," name : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
1229 fprintf(stderr," desc : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
1230 /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
1233 if ((ref->flags & RESOLVE_STATIC) == 0) {
1234 /* find the instance slot under all the parameter slots on the stack */
1235 instanceslot = stack;
1236 for (i=0; i<md->paramcount; ++i)
1237 instanceslot = instanceslot->prev;
1240 RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
1242 /* record subtype constraints for the instance type, if any */
1246 RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
1248 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
1249 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1250 { /* XXX clean up */
1251 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1252 classinfo *initclass = (ins) ? (classinfo*)ins[-1].val.a
1253 : refmethod->class; /* XXX classrefs */
1254 RESOLVE_ASSERT(initclass->loaded && initclass->linked);
1255 TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
1259 tip = &(instanceslot->typeinfo);
1261 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1262 &(ref->instancetypes),tip,methodref->classref))
1266 /* record subtype constraints for the parameter types, if any */
1268 for (i=md->paramcount-1; i>=0; --i, param=param->prev) {
1269 type = md->paramtypes[i].type;
1271 RESOLVE_ASSERT(param);
1272 RESOLVE_ASSERT(type == param->type);
1274 if (type == TYPE_ADR) {
1275 if (!ref->paramconstraints) {
1276 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
1277 for (j=md->paramcount-1; j>i; --j)
1278 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
1280 RESOLVE_ASSERT(ref->paramconstraints);
1281 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
1282 ref->paramconstraints + i,&(param->typeinfo),
1283 md->paramtypes[i].classref))
1287 if (ref->paramconstraints)
1288 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
1295 /******************************************************************************/
1296 /* FREEING MEMORY */
1297 /******************************************************************************/
1300 unresolved_subtype_set_free_list(classref_or_classinfo *list)
1303 classref_or_classinfo *p = list;
1305 /* this is silly. we *only* need to count the elements for MFREE */
1308 MFREE(list,classref_or_classinfo,(p - list));
1312 /* unresolved_class_free *******************************************************
1314 Free the memory used by an unresolved_class
1317 ref..............the unresolved_class
1319 *******************************************************************************/
1322 unresolved_class_free(unresolved_class *ref)
1324 RESOLVE_ASSERT(ref);
1326 unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
1327 FREE(ref,unresolved_class);
1330 /* unresolved_field_free *******************************************************
1332 Free the memory used by an unresolved_field
1335 ref..............the unresolved_field
1337 *******************************************************************************/
1340 unresolved_field_free(unresolved_field *ref)
1342 RESOLVE_ASSERT(ref);
1344 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1345 unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
1346 FREE(ref,unresolved_field);
1349 /* unresolved_method_free ******************************************************
1351 Free the memory used by an unresolved_method
1354 ref..............the unresolved_method
1356 *******************************************************************************/
1359 unresolved_method_free(unresolved_method *ref)
1361 RESOLVE_ASSERT(ref);
1363 unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
1364 if (ref->paramconstraints) {
1366 int count = ref->methodref->parseddesc.md->paramcount;
1368 for (i=0; i<count; ++i)
1369 unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
1370 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
1372 FREE(ref,unresolved_method);
1375 /******************************************************************************/
1377 /******************************************************************************/
1379 /* unresolved_subtype_set_debug_dump *******************************************
1381 Print debug info for unresolved_subtype_set to stream
1384 stset............the unresolved_subtype_set
1385 file.............the stream
1387 *******************************************************************************/
1390 unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
1392 classref_or_classinfo *p;
1394 if (SUBTYPESET_IS_EMPTY(*stset)) {
1395 fprintf(file," (empty)\n");
1398 p = stset->subtyperefs;
1399 for (;p->any; ++p) {
1400 if (IS_CLASSREF(*p)) {
1401 fprintf(file," ref: ");
1402 utf_fprint(file,p->ref->name);
1405 fprintf(file," cls: ");
1406 utf_fprint(file,p->cls->name);
1413 /* unresolved_class_debug_dump *************************************************
1415 Print debug info for unresolved_class to stream
1418 ref..............the unresolved_class
1419 file.............the stream
1421 *******************************************************************************/
1424 unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
1426 fprintf(file,"unresolved_class(%p):\n",(void *)ref);
1428 fprintf(file," referer : ");
1429 utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
1430 fprintf(file," refmethod : ");
1431 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1432 fprintf(file," refmethodd : ");
1433 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1434 fprintf(file," classname : ");
1435 utf_fprint(file,ref->classref->name); fputc('\n',file);
1436 fprintf(file," subtypeconstraints:\n");
1437 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
1441 /* unresolved_field_debug_dump *************************************************
1443 Print debug info for unresolved_field to stream
1446 ref..............the unresolved_field
1447 file.............the stream
1449 *******************************************************************************/
1452 unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
1454 fprintf(file,"unresolved_field(%p):\n",(void *)ref);
1456 fprintf(file," referer : ");
1457 utf_fprint(file,ref->fieldref->classref->referer->name); fputc('\n',file);
1458 fprintf(file," refmethod : ");
1459 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1460 fprintf(file," refmethodd : ");
1461 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1462 fprintf(file," classname : ");
1463 utf_fprint(file,ref->fieldref->classref->name); fputc('\n',file);
1464 fprintf(file," name : ");
1465 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
1466 fprintf(file," descriptor: ");
1467 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
1468 fprintf(file," parseddesc: ");
1469 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
1470 fprintf(file," flags : %04x\n",ref->flags);
1471 fprintf(file," instancetypes:\n");
1472 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1473 fprintf(file," valueconstraints:\n");
1474 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
1478 /* unresolved_method_debug_dump ************************************************
1480 Print debug info for unresolved_method to stream
1483 ref..............the unresolved_method
1484 file.............the stream
1486 *******************************************************************************/
1489 unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
1493 fprintf(file,"unresolved_method(%p):\n",(void *)ref);
1495 fprintf(file," referer : ");
1496 utf_fprint(file,ref->methodref->classref->referer->name); fputc('\n',file);
1497 fprintf(file," refmethod : ");
1498 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
1499 fprintf(file," refmethodd : ");
1500 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
1501 fprintf(file," classname : ");
1502 utf_fprint(file,ref->methodref->classref->name); fputc('\n',file);
1503 fprintf(file," name : ");
1504 utf_fprint(file,ref->methodref->name); fputc('\n',file);
1505 fprintf(file," descriptor: ");
1506 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
1507 fprintf(file," parseddesc: ");
1508 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
1509 fprintf(file," flags : %04x\n",ref->flags);
1510 fprintf(file," instancetypes:\n");
1511 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
1512 fprintf(file," paramconstraints:\n");
1513 if (ref->paramconstraints) {
1514 for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
1515 fprintf(file," param %d:\n",i);
1516 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
1520 fprintf(file," (empty)\n");
1526 * These are local overrides for various environment variables in Emacs.
1527 * Please do not remove this and leave it at the end of the file, where
1528 * Emacs will automagically detect them.
1529 * ---------------------------------------------------------------------
1532 * indent-tabs-mode: t
1536 * vim:noexpandtab:sw=4:ts=4: