* src/vm/resolve.c, src/vm/resolve.h
[cacao.git] / src / vm / resolve.c
1 /* src/vm/resolve.c - resolving classes/interfaces/fields/methods
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
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.
14
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.
19
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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Edwin Steiner
28
29    Changes: Christan Thalinger
30
31    $Id: resolve.c 5737 2006-10-11 19:40:22Z edwin $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39
40 #include "mm/memory.h"
41 #include "vm/resolve.h"
42 #include "vm/access.h"
43 #include "vm/classcache.h"
44 #include "vm/descriptor.h"
45 #include "vm/exceptions.h"
46 #include "vm/global.h"
47 #include "vm/linker.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/stringlocal.h"
51 #include "vm/jit/jit.h"
52 #include "vm/jit/verify/typeinfo.h"
53
54
55 /******************************************************************************/
56 /* DEBUG HELPERS                                                              */
57 /******************************************************************************/
58
59 /*#define RESOLVE_VERBOSE*/
60
61 /******************************************************************************/
62 /* CLASS RESOLUTION                                                           */
63 /******************************************************************************/
64
65 /* resolve_class_from_name *****************************************************
66  
67    Resolve a symbolic class reference
68   
69    IN:
70        referer..........the class containing the reference
71        refmethod........the method from which resolution was triggered
72                         (may be NULL if not applicable)
73        classname........class name to resolve
74        mode.............mode of resolution:
75                             resolveLazy...only resolve if it does not
76                                           require loading classes
77                             resolveEager..load classes if necessary
78            checkaccess......if true, access rights to the class are checked
79            link.............if true, guarantee that the returned class, if any,
80                             has been linked
81   
82    OUT:
83        *result..........set to result of resolution, or to NULL if
84                         the reference has not been resolved
85                         In the case of an exception, *result is
86                         guaranteed to be set to NULL.
87   
88    RETURN VALUE:
89        true.............everything ok 
90                         (*result may still be NULL for resolveLazy)
91        false............an exception has been thrown
92
93    NOTE:
94        The returned class is *not* guaranteed to be linked!
95            (It is guaranteed to be loaded, though.)
96    
97 *******************************************************************************/
98
99 bool resolve_class_from_name(classinfo *referer,
100                                                          methodinfo *refmethod,
101                                                          utf *classname,
102                                                          resolve_mode_t mode,
103                                                          bool checkaccess,
104                                                          bool link,
105                                                          classinfo **result)
106 {
107         classinfo *cls = NULL;
108         char *utf_ptr;
109         int len;
110         
111         assert(result);
112         assert(referer);
113         assert(classname);
114         assert(mode == resolveLazy || mode == resolveEager);
115         
116         *result = NULL;
117
118 #ifdef RESOLVE_VERBOSE
119         printf("resolve_class_from_name(");
120         utf_fprint_printable_ascii(stdout,referer->name);
121         printf(",%p,",(void*)referer->classloader);
122         utf_fprint_printable_ascii(stdout,classname);
123         printf(",%d,%d)\n",(int)checkaccess,(int)link);
124 #endif
125
126         /* lookup if this class has already been loaded */
127
128         cls = classcache_lookup(referer->classloader, classname);
129
130 #ifdef RESOLVE_VERBOSE
131         printf("    lookup result: %p\n",(void*)cls);
132 #endif
133
134         if (!cls) {
135                 /* resolve array types */
136
137                 if (classname->text[0] == '[') {
138                         utf_ptr = classname->text + 1;
139                         len = classname->blength - 1;
140
141                         /* classname is an array type name */
142
143                         switch (*utf_ptr) {
144                                 case 'L':
145                                         utf_ptr++;
146                                         len -= 2;
147                                         /* FALLTHROUGH */
148                                 case '[':
149                                         /* the component type is a reference type */
150                                         /* resolve the component type */
151                                         if (!resolve_class_from_name(referer,refmethod,
152                                                                            utf_new(utf_ptr,len),
153                                                                            mode,checkaccess,link,&cls))
154                                                 return false; /* exception */
155                                         if (!cls) {
156                                                 assert(mode == resolveLazy);
157                                                 return true; /* be lazy */
158                                         }
159                                         /* create the array class */
160                                         cls = class_array_of(cls,false);
161                                         if (!cls)
162                                                 return false; /* exception */
163                         }
164                 }
165                 else {
166                         /* the class has not been loaded, yet */
167                         if (mode == resolveLazy)
168                                 return true; /* be lazy */
169                 }
170
171 #ifdef RESOLVE_VERBOSE
172                 printf("    loading...\n");
173 #endif
174
175                 /* load the class */
176                 if (!cls) {
177                         if (!(cls = load_class_from_classloader(classname,
178                                                                                                         referer->classloader)))
179                                 return false; /* exception */
180                 }
181         }
182
183         /* the class is now loaded */
184         assert(cls);
185         assert(cls->state & CLASS_LOADED);
186
187 #ifdef RESOLVE_VERBOSE
188         printf("    checking access rights...\n");
189 #endif
190         
191         /* check access rights of referer to refered class */
192         if (checkaccess && !access_is_accessible_class(referer,cls)) {
193                 int msglen;
194                 char *message;
195
196                 msglen = utf_bytes(cls->name) + utf_bytes(referer->name) + 100;
197                 message = MNEW(char, msglen);
198                 strcpy(message, "class is not accessible (");
199                 utf_cat_classname(message, cls->name);
200                 strcat(message, " from ");
201                 utf_cat_classname(message, referer->name);
202                 strcat(message, ")");
203                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
204                 MFREE(message,char,msglen);
205                 return false; /* exception */
206         }
207
208         /* link the class if necessary */
209         if (link) {
210                 if (!(cls->state & CLASS_LINKED))
211                         if (!link_class(cls))
212                                 return false; /* exception */
213
214                 assert(cls->state & CLASS_LINKED);
215         }
216
217         /* resolution succeeds */
218 #ifdef RESOLVE_VERBOSE
219         printf("    success.\n");
220 #endif
221         *result = cls;
222         return true;
223 }
224
225 /* resolve_classref ************************************************************
226  
227    Resolve a symbolic class reference
228   
229    IN:
230        refmethod........the method from which resolution was triggered
231                         (may be NULL if not applicable)
232        ref..............class reference
233        mode.............mode of resolution:
234                             resolveLazy...only resolve if it does not
235                                           require loading classes
236                             resolveEager..load classes if necessary
237            checkaccess......if true, access rights to the class are checked
238            link.............if true, guarantee that the returned class, if any,
239                             has been linked
240   
241    OUT:
242        *result..........set to result of resolution, or to NULL if
243                         the reference has not been resolved
244                         In the case of an exception, *result is
245                         guaranteed to be set to NULL.
246   
247    RETURN VALUE:
248        true.............everything ok 
249                         (*result may still be NULL for resolveLazy)
250        false............an exception has been thrown
251    
252 *******************************************************************************/
253
254 bool resolve_classref(methodinfo *refmethod,
255                                           constant_classref *ref,
256                                           resolve_mode_t mode,
257                                           bool checkaccess,
258                                           bool link,
259                                           classinfo **result)
260 {
261         return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,checkaccess,link,result);
262 }
263
264 /* resolve_classref_or_classinfo ***********************************************
265  
266    Resolve a symbolic class reference if necessary
267   
268    IN:
269        refmethod........the method from which resolution was triggered
270                         (may be NULL if not applicable)
271        cls..............class reference or classinfo
272        mode.............mode of resolution:
273                             resolveLazy...only resolve if it does not
274                                           require loading classes
275                             resolveEager..load classes if necessary
276            checkaccess......if true, access rights to the class are checked
277            link.............if true, guarantee that the returned class, if any,
278                             has been linked
279   
280    OUT:
281        *result..........set to result of resolution, or to NULL if
282                         the reference has not been resolved
283                         In the case of an exception, *result is
284                         guaranteed to be set to NULL.
285   
286    RETURN VALUE:
287        true.............everything ok 
288                         (*result may still be NULL for resolveLazy)
289        false............an exception has been thrown
290    
291 *******************************************************************************/
292
293 bool resolve_classref_or_classinfo(methodinfo *refmethod,
294                                                                    classref_or_classinfo cls,
295                                                                    resolve_mode_t mode,
296                                                                    bool checkaccess,
297                                                                    bool link,
298                                                                    classinfo **result)
299 {
300         classinfo         *c;
301         
302         assert(cls.any);
303         assert(mode == resolveEager || mode == resolveLazy);
304         assert(result);
305
306 #ifdef RESOLVE_VERBOSE
307         printf("resolve_classref_or_classinfo(");
308         utf_fprint_printable_ascii(stdout,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
309         printf(",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
310 #endif
311
312         *result = NULL;
313
314         if (IS_CLASSREF(cls)) {
315                 /* we must resolve this reference */
316
317                 if (!resolve_class_from_name(cls.ref->referer, refmethod, cls.ref->name,
318                                                                          mode, checkaccess, link, &c))
319                         goto return_exception;
320
321         } else {
322                 /* cls has already been resolved */
323                 c = cls.cls;
324                 assert(c->state & CLASS_LOADED);
325         }
326         assert(c || (mode == resolveLazy));
327
328         if (!c)
329                 return true; /* be lazy */
330         
331         assert(c);
332         assert(c->state & CLASS_LOADED);
333
334         if (link) {
335                 if (!(c->state & CLASS_LINKED))
336                         if (!link_class(c))
337                                 goto return_exception;
338
339                 assert(c->state & CLASS_LINKED);
340         }
341
342         /* succeeded */
343         *result = c;
344         return true;
345
346  return_exception:
347         *result = NULL;
348         return false;
349 }
350
351
352 /* resolve_class_from_typedesc *************************************************
353  
354    Return a classinfo * for the given type descriptor
355   
356    IN:
357        d................type descriptor
358            checkaccess......if true, access rights to the class are checked
359            link.............if true, guarantee that the returned class, if any,
360                             has been linked
361    OUT:
362        *result..........set to result of resolution, or to NULL if
363                         the reference has not been resolved
364                         In the case of an exception, *result is
365                         guaranteed to be set to NULL.
366   
367    RETURN VALUE:
368        true.............everything ok 
369        false............an exception has been thrown
370
371    NOTE:
372        This function always resolves eagerly.
373    
374 *******************************************************************************/
375
376 bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
377 {
378         classinfo *cls;
379         
380         assert(d);
381         assert(result);
382
383         *result = NULL;
384
385 #ifdef RESOLVE_VERBOSE
386         printf("resolve_class_from_typedesc(");
387         descriptor_debug_print_typedesc(stdout,d);
388         printf(",%i,%i)\n",(int)checkaccess,(int)link);
389 #endif
390
391         if (d->type == TYPE_ADR) {
392                 /* a reference type */
393                 assert(d->classref);
394                 if (!resolve_classref_or_classinfo(NULL,CLASSREF_OR_CLASSINFO(d->classref),
395                                                                                    resolveEager,checkaccess,link,&cls))
396                         return false; /* exception */
397         }
398         else {
399                 /* a primitive type */
400                 cls = primitivetype_table[d->decltype].class_primitive;
401                 assert(cls->state & CLASS_LOADED);
402                 if (!(cls->state & CLASS_LINKED))
403                         if (!link_class(cls))
404                                 return false; /* exception */
405         }
406         assert(cls);
407         assert(cls->state & CLASS_LOADED);
408         assert(!link || (cls->state & CLASS_LINKED));
409
410 #ifdef RESOLVE_VERBOSE
411         printf("    result = ");utf_fprint_printable_ascii(stdout,cls->name);printf("\n");
412 #endif
413
414         *result = cls;
415         return true;
416 }
417
418 /******************************************************************************/
419 /* SUBTYPE SET CHECKS                                                         */
420 /******************************************************************************/
421
422 /* resolve_subtype_check *******************************************************
423  
424    Resolve the given types lazily and perform a subtype check
425   
426    IN:
427        refmethod........the method triggering the resolution
428        subtype..........checked to be a subtype of supertype
429            supertype........the super type to check agaings
430            mode.............mode of resolution:
431                             resolveLazy...only resolve if it does not
432                                           require loading classes
433                             resolveEager..load classes if necessary
434        error............which type of exception to throw if
435                         the test fails. May be:
436                             resolveLinkageError, or
437                             resolveIllegalAccessError
438                                                 IMPORTANT: If error==resolveIllegalAccessError,
439                                                 then array types are not checked.
440
441    RETURN VALUE:
442        resolveSucceeded.....the check succeeded
443        resolveDeferred......the check could not be performed due to
444                                 unresolved types. (This can only happen for
445                                                         mode == resolveLazy.)
446            resolveFailed........the check failed, an exception has been thrown.
447    
448    NOTE:
449            The types are resolved first, so any
450            exception which may occurr during resolution may
451            be thrown by this function.
452    
453 *******************************************************************************/
454
455 #if defined(ENABLE_VERIFIER)
456 static resolve_result_t resolve_subtype_check(methodinfo *refmethod,
457                                                                                       classref_or_classinfo subtype,
458                                                                                           classref_or_classinfo supertype,
459                                                                                           resolve_mode_t mode,
460                                                                                           resolve_err_t error)
461 {
462         classinfo *subclass;
463         typeinfo subti;
464         typecheck_result r;
465
466         assert(refmethod);
467         assert(subtype.any);
468         assert(supertype.any);
469         assert(mode == resolveLazy || mode == resolveEager);
470         assert(error == resolveLinkageError || error == resolveIllegalAccessError);
471
472         /* resolve the subtype */
473
474         if (!resolve_classref_or_classinfo(refmethod,subtype,mode,false,true,&subclass)) {
475                 /* the subclass could not be resolved. therefore we are sure that  */
476                 /* no instances of this subclass will ever exist -> skip this test */
477                 /* XXX this assumes that class loading has invariant results (as in JVM spec) */
478                 *exceptionptr = NULL;
479                 return resolveSucceeded;
480         }
481         if (!subclass)
482                 return resolveDeferred; /* be lazy */
483
484         assert(subclass->state & CLASS_LINKED);
485
486         /* do not check access to protected members of arrays */
487
488         if (error == resolveIllegalAccessError && subclass->name->text[0] == '[') {
489                 return resolveSucceeded;
490         }
491
492         /* perform the subtype check */
493
494         typeinfo_init_classinfo(&subti,subclass);
495 check_again:
496         r = typeinfo_is_assignable_to_class(&subti,supertype);
497         if (r == typecheck_FAIL)
498                 return resolveFailed; /* failed, exception is already set */
499
500         if (r == typecheck_MAYBE) {
501                 assert(IS_CLASSREF(supertype));
502                 if (mode == resolveEager) {
503                         if (!resolve_classref_or_classinfo(refmethod,supertype,
504                                                                                            resolveEager,false,true,
505                                                                                            &supertype.cls))
506                         {
507                                 return resolveFailed;
508                         }
509                         assert(supertype.cls);
510                         goto check_again;
511                 }
512
513                 return resolveDeferred; /* be lazy */
514         }
515
516         if (!r) {
517                 /* sub class relationship is false */
518
519                 char *message;
520                 int msglen;
521
522 #if defined(RESOLVE_VERBOSE)
523                 printf("SUBTYPE CHECK FAILED!\n");
524 #endif
525
526                 msglen = utf_bytes(subclass->name) + utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype)) + 200;
527                 message = MNEW(char, msglen);
528                 strcpy(message, (error == resolveIllegalAccessError) ?
529                                 "illegal access to protected member ("
530                                 : "subtype constraint violated (");
531                 utf_cat_classname(message, subclass->name);
532                 strcat(message, " is not a subclass of ");
533                 utf_cat_classname(message, CLASSREF_OR_CLASSINFO_NAME(supertype));
534                 strcat(message, ")");
535                 if (error == resolveIllegalAccessError)
536                         *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
537                 else
538                         *exceptionptr = exceptions_new_linkageerror(message, NULL);
539                 MFREE(message, char, msglen);
540                 return resolveFailed; /* exception */
541         }
542
543         /* everything ok */
544
545         return resolveSucceeded;
546 }
547 #endif /* defined(ENABLE_VERIFIER) */
548
549 /* resolve_lazy_subtype_checks *************************************************
550  
551    Resolve the types to check lazily and perform subtype checks
552   
553    IN:
554        refmethod........the method triggering the resolution
555        subtinfo.........the typeinfo containing the subtypes
556        supertype........the supertype to test againgst
557            mode.............mode of resolution:
558                             resolveLazy...only resolve if it does not
559                                           require loading classes
560                             resolveEager..load classes if necessary
561        error............which type of exception to throw if
562                         the test fails. May be:
563                             resolveLinkageError, or
564                             resolveIllegalAccessError
565                                                 IMPORTANT: If error==resolveIllegalAccessError,
566                                                 then array types in the set are skipped.
567
568    RETURN VALUE:
569        resolveSucceeded.....the check succeeded
570        resolveDeferred......the check could not be performed due to
571                                 unresolved types
572            resolveFailed........the check failed, an exception has been thrown.
573    
574    NOTE:
575        The references in the set are resolved first, so any
576        exception which may occurr during resolution may
577        be thrown by this function.
578    
579 *******************************************************************************/
580
581 #if defined(ENABLE_VERIFIER)
582 static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
583                                                                                                         typeinfo *subtinfo,
584                                                                                                         classref_or_classinfo supertype,
585                                                                                                         resolve_err_t error)
586 {
587         int count;
588         int i;
589         resolve_result_t result;
590
591         assert(refmethod);
592         assert(subtinfo);
593         assert(supertype.any);
594         assert(error == resolveLinkageError || error == resolveIllegalAccessError);
595
596         /* returnAddresses are illegal here */
597
598         if (TYPEINFO_IS_PRIMITIVE(*subtinfo)) {
599                 exceptions_throw_verifyerror(refmethod,
600                                 "Invalid use of returnAddress");
601                 return resolveFailed;
602         }
603
604         /* uninitialized objects are illegal here */
605
606         if (TYPEINFO_IS_NEWOBJECT(*subtinfo)) {
607                 exceptions_throw_verifyerror(refmethod,
608                                 "Invalid use of uninitialized object");
609                 return resolveFailed;
610         }
611
612         /* the nulltype is always assignable */
613
614         if (TYPEINFO_IS_NULLTYPE(*subtinfo))
615                 return resolveSucceeded;
616
617         /* every type is assignable to (BOOTSTRAP)java.lang.Object */
618
619         if (supertype.cls == class_java_lang_Object
620                 || (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
621                         && refmethod->class->classloader == NULL))
622         {
623                 return resolveSucceeded;
624         }
625
626         if (subtinfo->merged) {
627
628                 /* for a merged type we have to do a series of checks */
629
630                 count = subtinfo->merged->count;
631                 for (i=0; i<count; ++i) {
632                         classref_or_classinfo c = subtinfo->merged->list[i];
633                         if (subtinfo->dimension > 0) {
634                                 /* a merge of array types */
635                                 /* the merged list contains the possible _element_ types, */
636                                 /* so we have to create array types with these elements.  */
637                                 if (IS_CLASSREF(c)) {
638                                         c.ref = class_get_classref_multiarray_of(subtinfo->dimension,c.ref);
639                                 }
640                                 else {
641                                         c.cls = class_multiarray_of(subtinfo->dimension,c.cls,false);
642                                 }
643                         }
644
645                         /* do the subtype check against the type c */
646
647                         result = resolve_subtype_check(refmethod,c,supertype,resolveLazy,error);
648                         if (result != resolveSucceeded)
649                                 return result;
650                 }
651         }
652         else {
653
654                 /* a single type, this is the common case, hopefully */
655
656                 if (CLASSREF_OR_CLASSINFO_NAME(subtinfo->typeclass)
657                         == CLASSREF_OR_CLASSINFO_NAME(supertype))
658                 {
659                         /* the class names are the same */
660                     /* equality is guaranteed by the loading constraints */
661                         return resolveSucceeded;
662                 }
663                 else {
664
665                         /* some other type name, try to perform the check lazily */
666
667                         return resolve_subtype_check(refmethod,
668                                                                                  subtinfo->typeclass,supertype,
669                                                                                  resolveLazy,
670                                                                                  error);
671                 }
672         }
673
674         /* everything ok */
675         return resolveSucceeded;
676 }
677 #endif /* defined(ENABLE_VERIFIER) */
678
679 /* resolve_and_check_subtype_set ***********************************************
680  
681    Resolve the references in the given set and test subtype relationships
682   
683    IN:
684        refmethod........the method triggering the resolution
685        ref..............a set of class/interface references
686                         (may be empty)
687        typeref..........the type to test against the set
688        mode.............mode of resolution:
689                             resolveLazy...only resolve if it does not
690                                           require loading classes
691                             resolveEager..load classes if necessary
692        error............which type of exception to throw if
693                         the test fails. May be:
694                             resolveLinkageError, or
695                             resolveIllegalAccessError
696                                                 IMPORTANT: If error==resolveIllegalAccessError,
697                                                 then array types in the set are skipped.
698
699    RETURN VALUE:
700        resolveSucceeded.....the check succeeded
701        resolveDeferred......the check could not be performed due to
702                                 unresolved types. (This can only happen if
703                                                         mode == resolveLazy.)
704            resolveFailed........the check failed, an exception has been thrown.
705    
706    NOTE:
707        The references in the set are resolved first, so any
708        exception which may occurr during resolution may
709        be thrown by this function.
710    
711 *******************************************************************************/
712
713 #if defined(ENABLE_VERIFIER)
714 static resolve_result_t resolve_and_check_subtype_set(methodinfo *refmethod,
715                                                                           unresolved_subtype_set *ref,
716                                                                           classref_or_classinfo typeref,
717                                                                           resolve_mode_t mode,
718                                                                           resolve_err_t error)
719 {
720         classref_or_classinfo *setp;
721         typecheck_result checkresult;
722
723         assert(refmethod);
724         assert(ref);
725         assert(typeref.any);
726         assert(mode == resolveLazy || mode == resolveEager);
727         assert(error == resolveLinkageError || error == resolveIllegalAccessError);
728
729 #if defined(RESOLVE_VERBOSE)
730         printf("resolve_and_check_subtype_set:\n");
731         unresolved_subtype_set_debug_dump(ref, stdout);
732         if (IS_CLASSREF(typeref))
733                 class_classref_println(typeref.ref);
734         else
735                 class_println(typeref.cls);
736 #endif
737
738         setp = ref->subtyperefs;
739
740         /* an empty set of tests always succeeds */
741         if (!setp || !setp->any) {
742                 return resolveSucceeded;
743         }
744
745         /* first resolve the type if necessary */
746         if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&(typeref.cls)))
747                 return resolveFailed; /* exception */
748         if (!typeref.cls)
749                 return resolveDeferred; /* be lazy */
750
751         assert(typeref.cls->state & CLASS_LINKED);
752
753         /* iterate over the set members */
754
755         for (; setp->any; ++setp) {
756                 checkresult = resolve_subtype_check(refmethod,*setp,typeref,mode,error);
757 #if defined(RESOLVE_VERBOSE)
758                 if (checkresult != resolveSucceeded)
759                         printf("SUBTYPE CHECK FAILED!\n");
760 #endif
761                 if (checkresult != resolveSucceeded)
762                         return checkresult;
763         }
764
765         /* check succeeds */
766         return resolveSucceeded;
767 }
768 #endif /* defined(ENABLE_VERIFIER) */
769
770 /******************************************************************************/
771 /* CLASS RESOLUTION                                                           */
772 /******************************************************************************/
773
774 /* resolve_class ***************************************************************
775  
776    Resolve an unresolved class reference. The class is also linked.
777   
778    IN:
779        ref..............struct containing the reference
780        mode.............mode of resolution:
781                             resolveLazy...only resolve if it does not
782                                           require loading classes
783                             resolveEager..load classes if necessary
784            checkaccess......if true, access rights to the class are checked
785    
786    OUT:
787        *result..........set to the result of resolution, or to NULL if
788                         the reference has not been resolved
789                         In the case of an exception, *result is
790                         guaranteed to be set to NULL.
791   
792    RETURN VALUE:
793        true.............everything ok 
794                         (*result may still be NULL for resolveLazy)
795        false............an exception has been thrown
796    
797 *******************************************************************************/
798
799 #ifdef ENABLE_VERIFIER
800 bool resolve_class(unresolved_class *ref,
801                                    resolve_mode_t mode,
802                                    bool checkaccess,
803                                    classinfo **result)
804 {
805         classinfo *cls;
806         resolve_result_t checkresult;
807         
808         assert(ref);
809         assert(result);
810         assert(mode == resolveLazy || mode == resolveEager);
811
812         *result = NULL;
813
814 #ifdef RESOLVE_VERBOSE
815         unresolved_class_debug_dump(ref,stdout);
816 #endif
817
818         /* first we must resolve the class */
819         if (!resolve_classref(ref->referermethod,
820                                               ref->classref,mode,checkaccess,true,&cls))
821         {
822                 /* the class reference could not be resolved */
823                 return false; /* exception */
824         }
825         if (!cls)
826                 return true; /* be lazy */
827
828         assert(cls);
829         assert((cls->state & CLASS_LOADED) && (cls->state & CLASS_LINKED));
830
831         /* now we check the subtype constraints */
832         
833         checkresult = resolve_and_check_subtype_set(ref->referermethod,
834                                                                            &(ref->subtypeconstraints),
835                                                                            CLASSREF_OR_CLASSINFO(cls),
836                                                                            mode,
837                                                                            resolveLinkageError);
838         if (checkresult != resolveSucceeded)
839                 return (bool) checkresult;
840
841         /* succeed */
842         *result = cls;
843         return true;
844 }
845 #endif /* ENABLE_VERIFIER */
846
847 /* resolve_classref_eager ******************************************************
848  
849    Resolve an unresolved class reference eagerly. The class is also linked and
850    access rights to the class are checked.
851   
852    IN:
853        ref..............constant_classref to the class
854    
855    RETURN VALUE:
856        classinfo * to the class, or
857            NULL if an exception has been thrown
858    
859 *******************************************************************************/
860
861 classinfo * resolve_classref_eager(constant_classref *ref)
862 {
863         classinfo *c;
864
865         if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
866                 return NULL;
867
868         return c;
869 }
870
871 /* resolve_classref_eager_nonabstract ******************************************
872  
873    Resolve an unresolved class reference eagerly. The class is also linked and
874    access rights to the class are checked. A check is performed that the class
875    is not abstract.
876   
877    IN:
878        ref..............constant_classref to the class
879    
880    RETURN VALUE:
881        classinfo * to the class, or
882            NULL if an exception has been thrown
883    
884 *******************************************************************************/
885
886 classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
887 {
888         classinfo *c;
889
890         if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
891                 return NULL;
892
893         /* ensure that the class is not abstract */
894
895         if (c->flags & ACC_ABSTRACT) {
896                 exceptions_throw_verifyerror(NULL,"creating instance of abstract class");
897                 return NULL;
898         }
899
900         return c;
901 }
902
903 /* resolve_class_eager *********************************************************
904  
905    Resolve an unresolved class reference eagerly. The class is also linked and
906    access rights to the class are checked.
907   
908    IN:
909        ref..............struct containing the reference
910    
911    RETURN VALUE:
912        classinfo * to the class, or
913            NULL if an exception has been thrown
914    
915 *******************************************************************************/
916
917 #ifdef ENABLE_VERIFIER
918 classinfo * resolve_class_eager(unresolved_class *ref)
919 {
920         classinfo *c;
921
922         if (!resolve_class(ref,resolveEager,true,&c))
923                 return NULL;
924
925         return c;
926 }
927 #endif /* ENABLE_VERIFIER */
928
929 /******************************************************************************/
930 /* FIELD RESOLUTION                                                           */
931 /******************************************************************************/
932
933 /* resolve_field_verifier_checks *******************************************
934  
935    Do the verifier checks necessary after field has been resolved.
936   
937    IN:
938        refmethod........the method containing the reference
939            fieldref.........the field reference
940            container........the class where the field was found
941            fi...............the fieldinfo of the resolved field
942            instanceti.......instance typeinfo, if available
943            valueti..........value typeinfo, if available
944            isstatic.........true if this is a *STATIC* instruction
945            isput............true if this is a PUT* instruction
946   
947    RETURN VALUE:
948        resolveSucceeded....everything ok
949            resolveDeferred.....tests could not be done, have been deferred
950        resolveFailed.......exception has been thrown
951    
952 *******************************************************************************/
953
954 #if defined(ENABLE_VERIFIER)
955 resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
956                                                                                            constant_FMIref *fieldref,
957                                                                                            classinfo *container,
958                                                                                            fieldinfo *fi,
959                                                                                            typeinfo *instanceti,
960                                                                                            typeinfo *valueti,
961                                                                                            bool isstatic,
962                                                                                            bool isput)
963 {
964         classinfo *declarer;
965         classinfo *referer;
966         resolve_result_t result;
967         constant_classref *fieldtyperef;
968
969         assert(refmethod);
970         assert(fieldref);
971         assert(container);
972         assert(fi);
973
974         /* get the classinfos and the field type */
975
976         referer = refmethod->class;
977         assert(referer);
978
979         declarer = fi->class;
980         assert(declarer);
981         assert(referer->state & CLASS_LINKED);
982
983         fieldtyperef = fieldref->parseddesc.fd->classref;
984
985         /* check static */
986
987 #if true != 1
988 #error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
989 #endif
990
991         if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
992                 /* a static field is accessed via an instance, or vice versa */
993                 *exceptionptr =
994                         new_exception_message(string_java_lang_IncompatibleClassChangeError,
995                                 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
996                                                          : "instance field  accessed without instance");
997                 return resolveFailed;
998         }
999
1000         /* check access rights */
1001
1002         if (!access_is_accessible_member(referer,declarer,fi->flags)) {
1003                 int msglen;
1004                 char *message;
1005
1006                 msglen = utf_bytes(declarer->name) + utf_bytes(fi->name) + utf_bytes(referer->name) + 100;
1007                 message = MNEW(char, msglen);
1008                 strcpy(message, "field is not accessible (");
1009                 utf_cat_classname(message, declarer->name);
1010                 strcat(message, ".");
1011                 utf_cat(message, fi->name);
1012                 strcat(message, " from ");
1013                 utf_cat_classname(message, referer->name);
1014                 strcat(message, ")");
1015                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
1016                 MFREE(message,char,msglen);
1017                 return resolveFailed; /* exception */
1018         }
1019
1020         /* for non-static methods we have to check the constraints on the         */
1021         /* instance type                                                          */
1022
1023         if (instanceti) {
1024                 typeinfo *insttip;
1025                 typeinfo tinfo;
1026
1027                 /* The instanceslot must contain a reference to a non-array type */
1028
1029                 if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
1030                         exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
1031                         return resolveFailed;
1032                 }
1033                 if (TYPEINFO_IS_ARRAY(*instanceti)) {
1034                         exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
1035                         return resolveFailed;
1036                 }
1037
1038                 if (isput && TYPEINFO_IS_NEWOBJECT(*instanceti))
1039                 {
1040                         /* The instruction writes a field in an uninitialized object. */
1041                         /* This is only allowed when a field of an uninitialized 'this' object is */
1042                         /* written inside an initialization method                                */
1043
1044                         classinfo *initclass;
1045                         instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
1046
1047                         if (ins != NULL) {
1048                                 exceptions_throw_verifyerror(refmethod, "accessing field of uninitialized object");
1049                                 return resolveFailed;
1050                         }
1051
1052                         /* XXX check that class of field == refmethod->class */
1053                         initclass = referer; /* XXX classrefs */
1054                         assert(initclass->state & CLASS_LINKED);
1055
1056                         typeinfo_init_classinfo(&tinfo, initclass);
1057                         insttip = &tinfo;
1058                 }
1059                 else {
1060                         insttip = instanceti;
1061                 }
1062
1063                 result = resolve_lazy_subtype_checks(refmethod,
1064                                 insttip,
1065                                 CLASSREF_OR_CLASSINFO(container),
1066                                 resolveLinkageError);
1067                 if (result != resolveSucceeded)
1068                         return result;
1069
1070                 /* check protected access */
1071
1072                 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
1073                 {
1074                         result = resolve_lazy_subtype_checks(refmethod,
1075                                         instanceti,
1076                                         CLASSREF_OR_CLASSINFO(referer),
1077                                         resolveIllegalAccessError);
1078                         if (result != resolveSucceeded)
1079                                 return result;
1080                 }
1081
1082         }
1083
1084         /* for PUT* instructions we have to check the constraints on the value type */
1085
1086         if (valueti) {
1087                 assert(fieldtyperef);
1088
1089                 /* check subtype constraints */
1090                 result = resolve_lazy_subtype_checks(refmethod,
1091                                 valueti,
1092                                 CLASSREF_OR_CLASSINFO(fieldtyperef),
1093                                 resolveLinkageError);
1094
1095                 if (result != resolveSucceeded)
1096                         return result;
1097         }
1098
1099         /* impose loading constraint on field type */
1100
1101         if (fi->type == TYPE_ADR) {
1102                 assert(fieldtyperef);
1103                 if (!classcache_add_constraint(declarer->classloader,
1104                                                                            referer->classloader,
1105                                                                            fieldtyperef->name))
1106                         return resolveFailed;
1107         }
1108
1109         /* XXX impose loading constraint on instance? */
1110
1111         /* everything ok */
1112         return resolveSucceeded;
1113 }
1114 #endif /* defined(ENABLE_VERIFIER) */
1115
1116 /* resolve_field_lazy **********************************************************
1117  
1118    Resolve an unresolved field reference lazily
1119
1120    NOTE: This function does NOT do any verification checks. In case of a
1121          successful resolution, you must call resolve_field_verifier_checks
1122                  in order to perform the necessary checks!
1123   
1124    IN:
1125            refmethod........the referer method
1126            fieldref.........the field reference
1127   
1128    RETURN VALUE:
1129        resolveSucceeded.....the reference has been resolved
1130        resolveDeferred......the resolving could not be performed lazily
1131            resolveFailed........resolving failed, an exception has been thrown.
1132    
1133 *******************************************************************************/
1134
1135 resolve_result_t resolve_field_lazy(methodinfo *refmethod,
1136                                                                         constant_FMIref *fieldref)
1137 {
1138         classinfo *referer;
1139         classinfo *container;
1140         fieldinfo *fi;
1141
1142         assert(refmethod);
1143
1144         /* the class containing the reference */
1145
1146         referer = refmethod->class;
1147         assert(referer);
1148
1149         /* check if the field itself is already resolved */
1150
1151         if (IS_FMIREF_RESOLVED(fieldref))
1152                 return resolveSucceeded;
1153
1154         /* first we must resolve the class containg the field */
1155
1156         /* XXX can/may lazyResolving trigger linking? */
1157
1158         if (!resolve_class_from_name(referer, refmethod,
1159                    fieldref->p.classref->name, resolveLazy, true, true, &container))
1160         {
1161                 /* the class reference could not be resolved */
1162                 return resolveFailed; /* exception */
1163         }
1164         if (!container)
1165                 return resolveDeferred; /* be lazy */
1166
1167         assert(container->state & CLASS_LINKED);
1168
1169         /* now we must find the declaration of the field in `container`
1170          * or one of its superclasses */
1171
1172         fi = class_resolvefield(container,
1173                                                         fieldref->name, fieldref->descriptor,
1174                                                         referer, true);
1175         if (!fi) {
1176                 /* The field does not exist. But since we were called lazily, */
1177                 /* this error must not be reported now. (It will be reported   */
1178                 /* if eager resolving of this field is ever tried.)           */
1179
1180                 *exceptionptr = NULL;
1181                 return resolveDeferred; /* be lazy */
1182         }
1183
1184         /* cache the result of the resolution */
1185
1186         fieldref->p.field = fi;
1187
1188         /* everything ok */
1189         return resolveSucceeded;
1190 }
1191
1192 /* resolve_field ***************************************************************
1193  
1194    Resolve an unresolved field reference
1195   
1196    IN:
1197        ref..............struct containing the reference
1198        mode.............mode of resolution:
1199                             resolveLazy...only resolve if it does not
1200                                           require loading classes
1201                             resolveEager..load classes if necessary
1202   
1203    OUT:
1204        *result..........set to the result of resolution, or to NULL if
1205                         the reference has not been resolved
1206                         In the case of an exception, *result is
1207                         guaranteed to be set to NULL.
1208   
1209    RETURN VALUE:
1210        true.............everything ok 
1211                         (*result may still be NULL for resolveLazy)
1212        false............an exception has been thrown
1213    
1214 *******************************************************************************/
1215
1216 bool resolve_field(unresolved_field *ref,
1217                                    resolve_mode_t mode,
1218                                    fieldinfo **result)
1219 {
1220         classinfo *referer;
1221         classinfo *container;
1222         classinfo *declarer;
1223         constant_classref *fieldtyperef;
1224         fieldinfo *fi;
1225         resolve_result_t checkresult;
1226
1227         assert(ref);
1228         assert(result);
1229         assert(mode == resolveLazy || mode == resolveEager);
1230
1231         *result = NULL;
1232
1233 #ifdef RESOLVE_VERBOSE
1234         unresolved_field_debug_dump(ref,stdout);
1235 #endif
1236
1237         /* the class containing the reference */
1238
1239         referer = ref->referermethod->class;
1240         assert(referer);
1241
1242         /* check if the field itself is already resolved */
1243         if (IS_FMIREF_RESOLVED(ref->fieldref)) {
1244                 fi = ref->fieldref->p.field;
1245                 container = fi->class;
1246                 goto resolved_the_field;
1247         }
1248
1249         /* first we must resolve the class containg the field */
1250         if (!resolve_class_from_name(referer,ref->referermethod,
1251                                            ref->fieldref->p.classref->name,mode,true,true,&container))
1252         {
1253                 /* the class reference could not be resolved */
1254                 return false; /* exception */
1255         }
1256         if (!container)
1257                 return true; /* be lazy */
1258
1259         assert(container);
1260         assert(container->state & CLASS_LOADED);
1261         assert(container->state & CLASS_LINKED);
1262
1263         /* now we must find the declaration of the field in `container`
1264          * or one of its superclasses */
1265
1266 #ifdef RESOLVE_VERBOSE
1267                 printf("    resolving field in class...\n");
1268 #endif
1269
1270         fi = class_resolvefield(container,
1271                                                         ref->fieldref->name,ref->fieldref->descriptor,
1272                                                         referer,true);
1273         if (!fi) {
1274                 if (mode == resolveLazy) {
1275                         /* The field does not exist. But since we were called lazily, */
1276                         /* this error must not be reported now. (It will be reported   */
1277                         /* if eager resolving of this field is ever tried.)           */
1278
1279                         *exceptionptr = NULL;
1280                         return true; /* be lazy */
1281                 }
1282
1283                 return false; /* exception */
1284         }
1285
1286         /* cache the result of the resolution */
1287         ref->fieldref->p.field = fi;
1288
1289 resolved_the_field:
1290
1291 #ifdef ENABLE_VERIFIER
1292         /* Checking opt_verify is ok here, because the NULL iptr guarantees */
1293         /* that no missing parts of an instruction will be accessed.        */
1294         if (opt_verify) {
1295                 checkresult = resolve_field_verifier_checks(
1296                                 ref->referermethod,
1297                                 ref->fieldref,
1298                                 container,
1299                                 fi,
1300                                 NULL, /* instanceti, handled by constraints below */
1301                                 NULL, /* valueti, handled by constraints below  */
1302                                 (ref->flags & RESOLVE_STATIC) != 0, /* isstatic */
1303                                 (ref->flags & RESOLVE_PUTFIELD) != 0 /* isput */);
1304
1305                 if (checkresult != resolveSucceeded)
1306                         return (bool) checkresult;
1307
1308                 declarer = fi->class;
1309                 assert(declarer);
1310                 assert(declarer->state & CLASS_LOADED);
1311                 assert(declarer->state & CLASS_LINKED);
1312
1313                 /* for non-static accesses we have to check the constraints on the */
1314                 /* instance type */
1315
1316                 if (!(ref->flags & RESOLVE_STATIC)) {
1317                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
1318                                         &(ref->instancetypes),
1319                                         CLASSREF_OR_CLASSINFO(container),
1320                                         mode, resolveLinkageError);
1321                         if (checkresult != resolveSucceeded)
1322                                 return (bool) checkresult;
1323                 }
1324
1325                 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
1326
1327                 /* for PUT* instructions we have to check the constraints on the value type */
1328                 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
1329                         assert(fieldtyperef);
1330                         if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
1331                                 /* check subtype constraints */
1332                                 checkresult = resolve_and_check_subtype_set(ref->referermethod,
1333                                                 &(ref->valueconstraints),
1334                                                 CLASSREF_OR_CLASSINFO(fieldtyperef),
1335                                                 mode, resolveLinkageError);
1336                                 if (checkresult != resolveSucceeded)
1337                                         return (bool) checkresult;
1338                         }
1339                 }
1340
1341                 /* check protected access */
1342                 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
1343                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
1344                                         &(ref->instancetypes),
1345                                         CLASSREF_OR_CLASSINFO(referer),
1346                                         mode,
1347                                         resolveIllegalAccessError);
1348                         if (checkresult != resolveSucceeded)
1349                                 return (bool) checkresult;
1350                 }
1351
1352         }
1353 #endif /* ENABLE_VERIFIER */
1354
1355         /* succeed */
1356         *result = fi;
1357
1358         return true;
1359 }
1360
1361 /* resolve_field_eager *********************************************************
1362  
1363    Resolve an unresolved field reference eagerly.
1364   
1365    IN:
1366        ref..............struct containing the reference
1367    
1368    RETURN VALUE:
1369        fieldinfo * to the field, or
1370            NULL if an exception has been thrown
1371    
1372 *******************************************************************************/
1373
1374 fieldinfo * resolve_field_eager(unresolved_field *ref)
1375 {
1376         fieldinfo *fi;
1377
1378         if (!resolve_field(ref,resolveEager,&fi))
1379                 return NULL;
1380
1381         return fi;
1382 }
1383
1384 /******************************************************************************/
1385 /* METHOD RESOLUTION                                                          */
1386 /******************************************************************************/
1387
1388 /* resolve_method_invokespecial_lookup *****************************************
1389  
1390    Do the special lookup for methods invoked by INVOKESPECIAL
1391   
1392    IN:
1393        refmethod........the method containing the reference
1394            mi...............the methodinfo of the resolved method
1395   
1396    RETURN VALUE:
1397        a methodinfo *...the result of the lookup,
1398            NULL.............an exception has been thrown
1399    
1400 *******************************************************************************/
1401
1402 methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
1403                                                                                                  methodinfo *mi)
1404 {
1405         classinfo *declarer;
1406         classinfo *referer;
1407
1408         assert(refmethod);
1409         assert(mi);
1410
1411         /* get referer and declarer classes */
1412
1413         referer = refmethod->class;
1414         assert(referer);
1415
1416         declarer = mi->class;
1417         assert(declarer);
1418         assert(referer->state & CLASS_LINKED);
1419
1420         /* checks for INVOKESPECIAL:                                       */
1421         /* for <init> and methods of the current class we don't need any   */
1422         /* special checks. Otherwise we must verify that the called method */
1423         /* belongs to a super class of the current class                   */
1424
1425         if ((referer != declarer) && (mi->name != utf_init)) {
1426                 /* check that declarer is a super class of the current class   */
1427
1428                 if (!class_issubclass(referer,declarer)) {
1429                         exceptions_throw_verifyerror(refmethod,
1430                                         "INVOKESPECIAL calling non-super class method");
1431                         return NULL;
1432                 }
1433
1434                 /* if the referer has ACC_SUPER set, we must do the special    */
1435                 /* lookup starting with the direct super class of referer      */
1436
1437                 if ((referer->flags & ACC_SUPER) != 0) {
1438                         mi = class_resolvemethod(referer->super.cls,
1439                                                                          mi->name,
1440                                                                          mi->descriptor);
1441
1442                         if (mi == NULL) {
1443                                 /* the spec calls for an AbstractMethodError in this case */
1444                                 exceptions_throw_abstractmethoderror();
1445                                 return NULL;
1446                         }
1447                 }
1448         }
1449
1450         /* everything ok */
1451         return mi;
1452 }
1453
1454 /* resolve_method_verifier_checks ******************************************
1455  
1456    Do the verifier checks necessary after a method has been resolved.
1457   
1458    IN:
1459        refmethod........the method containing the reference
1460            methodref........the method reference
1461            mi...............the methodinfo of the resolved method
1462            invokestatic.....true if the method is invoked by INVOKESTATIC
1463   
1464    RETURN VALUE:
1465        resolveSucceeded....everything ok
1466            resolveDeferred.....tests could not be done, have been deferred
1467        resolveFailed.......exception has been thrown
1468    
1469 *******************************************************************************/
1470
1471 #if defined(ENABLE_VERIFIER)
1472 resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
1473                                                                                                 constant_FMIref *methodref,
1474                                                                                                 methodinfo *mi,
1475                                                                                                 bool invokestatic)
1476 {
1477         classinfo *declarer;
1478         classinfo *referer;
1479
1480         assert(refmethod);
1481         assert(methodref);
1482         assert(mi);
1483
1484 #ifdef RESOLVE_VERBOSE
1485         printf("resolve_method_verifier_checks\n");
1486         printf("    flags: %02x\n",mi->flags);
1487 #endif
1488
1489         /* get the classinfos and the method descriptor */
1490
1491         referer = refmethod->class;
1492         assert(referer);
1493
1494         declarer = mi->class;
1495         assert(declarer);
1496
1497         /* check static */
1498
1499         if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
1500                 /* a static method is accessed via an instance, or vice versa */
1501                 *exceptionptr =
1502                         new_exception_message(string_java_lang_IncompatibleClassChangeError,
1503                                 (mi->flags & ACC_STATIC) ? "static method called via instance"
1504                                                          : "instance method called without instance");
1505                 return resolveFailed;
1506         }
1507
1508         /* check access rights */
1509
1510         if (!access_is_accessible_member(referer,declarer,mi->flags)) {
1511                 int msglen;
1512                 char *message;
1513
1514                 /* XXX clean this up. this should be in exceptions.c */
1515                 msglen = utf_bytes(declarer->name) + utf_bytes(mi->name) +
1516                         utf_bytes(mi->descriptor) + utf_bytes(referer->name) + 100;
1517                 message = MNEW(char, msglen);
1518                 strcpy(message, "method is not accessible (");
1519                 utf_cat_classname(message, declarer->name);
1520                 strcat(message, ".");
1521                 utf_cat(message, mi->name);
1522                 utf_cat(message, mi->descriptor);
1523                 strcat(message," from ");
1524                 utf_cat_classname(message, referer->name);
1525                 strcat(message,")");
1526                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
1527                 MFREE(message, char, msglen);
1528                 return resolveFailed; /* exception */
1529         }
1530
1531         /* everything ok */
1532
1533         return resolveSucceeded;
1534 }
1535 #endif /* defined(ENABLE_VERIFIER) */
1536
1537
1538 /* resolve_method_instance_type_checks *****************************************
1539
1540    Check the instance type of a method invocation.
1541
1542    IN:
1543        refmethod........the method containing the reference
1544            mi...............the methodinfo of the resolved method
1545            instanceti.......typeinfo of the instance slot
1546            invokespecial....true if the method is invoked by INVOKESPECIAL
1547
1548    RETURN VALUE:
1549        resolveSucceeded....everything ok
1550            resolveDeferred.....tests could not be done, have been deferred
1551        resolveFailed.......exception has been thrown
1552
1553 *******************************************************************************/
1554
1555 #if defined(ENABLE_VERIFIER)
1556 resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
1557                                                                                                          methodinfo *mi,
1558                                                                                                          typeinfo *instanceti,
1559                                                                                                          bool invokespecial)
1560 {
1561         typeinfo         tinfo;
1562         typeinfo        *tip;
1563         resolve_result_t result;
1564
1565         if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
1566         {   /* XXX clean up */
1567                 instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
1568                 classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
1569                                                                          : CLASSREF_OR_CLASSINFO(refmethod->class);
1570                 tip = &tinfo;
1571                 if (!typeinfo_init_class(tip, initclass))
1572                         return false;
1573         }
1574         else {
1575                 tip = instanceti;
1576         }
1577
1578         result = resolve_lazy_subtype_checks(refmethod,
1579                                                                                  tip,
1580                                                                                  CLASSREF_OR_CLASSINFO(mi->class),
1581                                                                                  resolveLinkageError);
1582         if (result != resolveSucceeded)
1583                 return result;
1584
1585         /* check protected access */
1586
1587         /* XXX use other `declarer` than mi->class? */
1588         if (((mi->flags & ACC_PROTECTED) != 0)
1589                         && !SAME_PACKAGE(mi->class, refmethod->class))
1590         {
1591                 result = resolve_lazy_subtype_checks(refmethod,
1592                                 tip,
1593                                 CLASSREF_OR_CLASSINFO(refmethod->class),
1594                                 resolveIllegalAccessError);
1595                 if (result != resolveSucceeded)
1596                         return result;
1597         }
1598
1599         /* everything ok */
1600
1601         return resolveSucceeded;
1602 }
1603 #endif /* defined(ENABLE_VERIFIER) */
1604
1605
1606 /* resolve_method_param_type_checks ********************************************
1607
1608    Check non-instance parameter types of a method invocation.
1609
1610    IN:
1611            jd...............jitdata of the method doing the call
1612        refmethod........the method containing the reference
1613            iptr.............the invoke instruction
1614            mi...............the methodinfo of the resolved method
1615            invokestatic.....true if the method is invoked by INVOKESTATIC
1616
1617    RETURN VALUE:
1618        resolveSucceeded....everything ok
1619            resolveDeferred.....tests could not be done, have been deferred
1620        resolveFailed.......exception has been thrown
1621
1622 *******************************************************************************/
1623
1624 #if defined(ENABLE_VERIFIER)
1625 resolve_result_t resolve_method_param_type_checks(jitdata *jd, 
1626                                                                                                   methodinfo *refmethod,
1627                                                                                                   instruction *iptr, 
1628                                                                                                   methodinfo *mi,
1629                                                                                                   bool invokestatic)
1630 {
1631         varinfo         *param;
1632         resolve_result_t result;
1633         methoddesc      *md;
1634         typedesc        *paramtypes;
1635         s4               type;
1636         s4               instancecount;
1637         s4               i;
1638
1639         assert(jd);
1640
1641         instancecount = (invokestatic) ? 0 : 1;
1642
1643         /* check subtype constraints for TYPE_ADR parameters */
1644
1645         md = mi->parseddesc;
1646         paramtypes = md->paramtypes;
1647
1648         for (i = md->paramcount-1-instancecount; i>=0; --i) {
1649                 param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
1650                 type = md->paramtypes[i+instancecount].type;
1651
1652                 assert(param);
1653                 assert(type == param->type);
1654
1655                 if (type == TYPE_ADR) {
1656                         result = resolve_lazy_subtype_checks(refmethod,
1657                                         &(param->typeinfo),
1658                                         CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
1659                                         resolveLinkageError);
1660                         if (result != resolveSucceeded)
1661                                 return result;
1662                 }
1663         }
1664
1665         /* everything ok */
1666
1667         return resolveSucceeded;
1668 }
1669 #endif /* defined(ENABLE_VERIFIER) */
1670
1671
1672 /* resolve_method_param_type_checks_stackbased *********************************
1673
1674    Check non-instance parameter types of a method invocation.
1675
1676    IN:
1677        refmethod........the method containing the reference
1678            mi...............the methodinfo of the resolved method
1679            invokestatic.....true if the method is invoked by INVOKESTATIC
1680            stack............TOS before the INVOKE instruction
1681
1682    RETURN VALUE:
1683        resolveSucceeded....everything ok
1684            resolveDeferred.....tests could not be done, have been deferred
1685        resolveFailed.......exception has been thrown
1686
1687 *******************************************************************************/
1688
1689 #if defined(ENABLE_VERIFIER)
1690 resolve_result_t resolve_method_param_type_checks_stackbased(
1691                 methodinfo *refmethod, 
1692                 methodinfo *mi,
1693                 bool invokestatic, 
1694                 typedescriptor *stack)
1695 {
1696         typedescriptor  *param;
1697         resolve_result_t result;
1698         methoddesc      *md;
1699         typedesc        *paramtypes;
1700         s4               type;
1701         s4               instancecount;
1702         s4               i;
1703
1704         instancecount = (invokestatic) ? 0 : 1;
1705
1706         /* check subtype constraints for TYPE_ADR parameters */
1707
1708         md = mi->parseddesc;
1709         paramtypes = md->paramtypes;
1710
1711         param = stack - (md->paramslots - 1 - instancecount);
1712
1713         for (i = instancecount; i < md->paramcount; ++i) {
1714                 type = md->paramtypes[i].type;
1715
1716                 assert(type == param->type);
1717
1718                 if (type == TYPE_ADR) {
1719                         result = resolve_lazy_subtype_checks(refmethod,
1720                                         &(param->typeinfo),
1721                                         CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
1722                                         resolveLinkageError);
1723                         if (result != resolveSucceeded)
1724                                 return result;
1725                 }
1726
1727                 param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
1728         }
1729
1730         /* everything ok */
1731
1732         return resolveSucceeded;
1733 }
1734 #endif /* defined(ENABLE_VERIFIER) */
1735
1736
1737 /* resolve_method_loading_constraints ******************************************
1738
1739    Impose loading constraints on the parameters and return type of the
1740    given method.
1741
1742    IN:
1743        referer..........the class refering to the method
1744            mi...............the method
1745
1746    RETURN VALUE:
1747        true................everything ok
1748            false...............an exception has been thrown
1749
1750 *******************************************************************************/
1751
1752 #if defined(ENABLE_VERIFIER)
1753 bool resolve_method_loading_constraints(classinfo *referer,
1754                                                                                 methodinfo *mi)
1755 {
1756         methoddesc *md;
1757         typedesc   *paramtypes;
1758         utf        *name;
1759         s4          i;
1760         s4          instancecount;
1761
1762         /* impose loading constraints on parameters (including instance) */
1763
1764         md = mi->parseddesc;
1765         paramtypes = md->paramtypes;
1766         instancecount = (mi->flags & ACC_STATIC) / ACC_STATIC;
1767
1768         for (i = 0; i < md->paramcount; i++) {
1769                 if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
1770                         if (i < instancecount) {
1771                                 /* The type of the 'this' pointer is the class containing */
1772                                 /* the method definition. Since container is the same as, */
1773                                 /* or a subclass of declarer, we also constrain declarer  */
1774                                 /* by transitivity of loading constraints.                */
1775                                 name = mi->class->name;
1776                         }
1777                         else {
1778                                 name = paramtypes[i].classref->name;
1779                         }
1780
1781                         /* The caller (referer) and the callee (container) must agree */
1782                         /* on the types of the parameters.                            */
1783                         if (!classcache_add_constraint(referer->classloader,
1784                                                                                    mi->class->classloader, name))
1785                                 return false; /* exception */
1786                 }
1787         }
1788
1789         /* impose loading constraint onto return type */
1790
1791         if (md->returntype.type == TYPE_ADR) {
1792                 /* The caller (referer) and the callee (container) must agree */
1793                 /* on the return type.                                        */
1794                 if (!classcache_add_constraint(referer->classloader,
1795                                         mi->class->classloader,
1796                                         md->returntype.classref->name))
1797                         return false; /* exception */
1798         }
1799
1800         /* everything ok */
1801
1802         return true;
1803 }
1804 #endif /* defined(ENABLE_VERIFIER) */
1805
1806
1807 /* resolve_method_lazy *********************************************************
1808  
1809    Resolve an unresolved method reference lazily
1810   
1811    NOTE: This function does NOT do any verification checks. In case of a
1812          successful resolution, you must call resolve_method_verifier_checks
1813                  in order to perform the necessary checks!
1814   
1815    IN:
1816            refmethod........the referer method
1817            methodref........the method reference
1818            invokespecial....true if this is an INVOKESPECIAL instruction
1819   
1820    RETURN VALUE:
1821        resolveSucceeded.....the reference has been resolved
1822        resolveDeferred......the resolving could not be performed lazily
1823            resolveFailed........resolving failed, an exception has been thrown.
1824    
1825 *******************************************************************************/
1826
1827 resolve_result_t resolve_method_lazy(methodinfo *refmethod,
1828                                                                          constant_FMIref *methodref,
1829                                                                          bool invokespecial)
1830 {
1831         classinfo *referer;
1832         classinfo *container;
1833         methodinfo *mi;
1834
1835         assert(refmethod);
1836
1837 #ifdef RESOLVE_VERBOSE
1838         printf("resolve_method_lazy\n");
1839 #endif
1840
1841         /* the class containing the reference */
1842
1843         referer = refmethod->class;
1844         assert(referer);
1845
1846         /* check if the method itself is already resolved */
1847
1848         if (IS_FMIREF_RESOLVED(methodref))
1849                 return resolveSucceeded;
1850
1851         /* first we must resolve the class containg the method */
1852
1853         if (!resolve_class_from_name(referer, refmethod,
1854                    methodref->p.classref->name, resolveLazy, true, true, &container))
1855         {
1856                 /* the class reference could not be resolved */
1857                 return resolveFailed; /* exception */
1858         }
1859         if (!container)
1860                 return resolveDeferred; /* be lazy */
1861
1862         assert(container->state & CLASS_LINKED);
1863
1864         /* now we must find the declaration of the method in `container`
1865          * or one of its superclasses */
1866
1867         if (container->flags & ACC_INTERFACE) {
1868                 mi = class_resolveinterfacemethod(container,
1869                                                                               methodref->name,
1870                                                                                   methodref->descriptor,
1871                                                                               referer, true);
1872
1873         } else {
1874                 mi = class_resolveclassmethod(container,
1875                                                                           methodref->name,
1876                                                                           methodref->descriptor,
1877                                                                           referer, true);
1878         }
1879
1880         if (!mi) {
1881                 /* The method does not exist. But since we were called lazily, */
1882                 /* this error must not be reported now. (It will be reported   */
1883                 /* if eager resolving of this method is ever tried.)           */
1884
1885                 *exceptionptr = NULL;
1886                 return resolveDeferred; /* be lazy */
1887         }
1888
1889         if (invokespecial) {
1890                 mi = resolve_method_invokespecial_lookup(refmethod, mi);
1891                 if (!mi)
1892                         return resolveFailed; /* exception */
1893         }
1894
1895         /* have the method params already been parsed? no, do it. */
1896
1897         if (!mi->parseddesc->params)
1898                 if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
1899                         return resolveFailed;
1900
1901         /* cache the result of the resolution */
1902
1903         methodref->p.method = mi;
1904
1905         /* succeed */
1906
1907         return resolveSucceeded;
1908 }
1909
1910 /* resolve_method **************************************************************
1911  
1912    Resolve an unresolved method reference
1913   
1914    IN:
1915        ref..............struct containing the reference
1916        mode.............mode of resolution:
1917                             resolveLazy...only resolve if it does not
1918                                           require loading classes
1919                             resolveEager..load classes if necessary
1920   
1921    OUT:
1922        *result..........set to the result of resolution, or to NULL if
1923                         the reference has not been resolved
1924                         In the case of an exception, *result is
1925                         guaranteed to be set to NULL.
1926   
1927    RETURN VALUE:
1928        true.............everything ok 
1929                         (*result may still be NULL for resolveLazy)
1930        false............an exception has been thrown
1931    
1932 *******************************************************************************/
1933
1934 bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
1935 {
1936         classinfo *referer;
1937         classinfo *container;
1938         classinfo *declarer;
1939         methodinfo *mi;
1940         typedesc *paramtypes;
1941         int instancecount;
1942         int i;
1943         resolve_result_t checkresult;
1944
1945         assert(ref);
1946         assert(result);
1947         assert(mode == resolveLazy || mode == resolveEager);
1948
1949 #ifdef RESOLVE_VERBOSE
1950         unresolved_method_debug_dump(ref,stdout);
1951 #endif
1952
1953         *result = NULL;
1954
1955         /* the class containing the reference */
1956
1957         referer = ref->referermethod->class;
1958         assert(referer);
1959
1960         /* check if the method itself is already resolved */
1961
1962         if (IS_FMIREF_RESOLVED(ref->methodref)) {
1963                 mi = ref->methodref->p.method;
1964                 container = mi->class;
1965                 goto resolved_the_method;
1966         }
1967
1968         /* first we must resolve the class containing the method */
1969
1970         if (!resolve_class_from_name(referer,ref->referermethod,
1971                                            ref->methodref->p.classref->name,mode,true,true,&container))
1972         {
1973                 /* the class reference could not be resolved */
1974                 return false; /* exception */
1975         }
1976         if (!container)
1977                 return true; /* be lazy */
1978
1979         assert(container);
1980         assert(container->state & CLASS_LINKED);
1981
1982         /* now we must find the declaration of the method in `container`
1983          * or one of its superclasses */
1984
1985         if (container->flags & ACC_INTERFACE) {
1986                 mi = class_resolveinterfacemethod(container,
1987                                                                               ref->methodref->name,
1988                                                                                   ref->methodref->descriptor,
1989                                                                               referer, true);
1990
1991         } else {
1992                 mi = class_resolveclassmethod(container,
1993                                                                           ref->methodref->name,
1994                                                                           ref->methodref->descriptor,
1995                                                                           referer, true);
1996         }
1997
1998         if (!mi) {
1999                 if (mode == resolveLazy) {
2000                         /* The method does not exist. But since we were called lazily, */
2001                         /* this error must not be reported now. (It will be reported   */
2002                         /* if eager resolving of this method is ever tried.)           */
2003
2004                         *exceptionptr = NULL;
2005                         return true; /* be lazy */
2006                 }
2007
2008                 return false; /* exception */ /* XXX set exceptionptr? */
2009         }
2010
2011         /* { the method reference has been resolved } */
2012
2013         if (ref->flags & RESOLVE_SPECIAL) {
2014                 mi = resolve_method_invokespecial_lookup(ref->referermethod,mi);
2015                 if (!mi)
2016                         return false; /* exception */
2017         }
2018
2019         /* have the method params already been parsed? no, do it. */
2020
2021         if (!mi->parseddesc->params)
2022                 if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
2023                         return false;
2024
2025         /* cache the resolution */
2026
2027         ref->methodref->p.method = mi;
2028
2029 resolved_the_method:
2030
2031 #ifdef ENABLE_VERIFIER
2032         if (opt_verify) {
2033
2034                 checkresult = resolve_method_verifier_checks(
2035                                 ref->referermethod,
2036                                 ref->methodref,
2037                                 mi,
2038                                 (ref->flags & RESOLVE_STATIC));
2039
2040                 if (checkresult != resolveSucceeded)
2041                         return (bool) checkresult;
2042
2043                 /* impose loading constraints on params and return type */
2044
2045                 if (!resolve_method_loading_constraints(referer, mi))
2046                         return false;
2047
2048                 declarer = mi->class;
2049                 assert(declarer);
2050                 assert(referer->state & CLASS_LINKED);
2051
2052                 /* for non-static methods we have to check the constraints on the         */
2053                 /* instance type                                                          */
2054
2055                 if (!(ref->flags & RESOLVE_STATIC)) {
2056                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
2057                                         &(ref->instancetypes),
2058                                         CLASSREF_OR_CLASSINFO(container),
2059                                         mode,
2060                                         resolveLinkageError);
2061                         if (checkresult != resolveSucceeded)
2062                                 return (bool) checkresult;
2063                         instancecount = 1;
2064                 }
2065                 else {
2066                         instancecount = 0;
2067                 }
2068
2069                 /* check subtype constraints for TYPE_ADR parameters */
2070
2071                 assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
2072                 paramtypes = mi->parseddesc->paramtypes;
2073
2074                 for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
2075                         if (paramtypes[i+instancecount].type == TYPE_ADR) {
2076                                 if (ref->paramconstraints) {
2077                                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
2078                                                         ref->paramconstraints + i,
2079                                                         CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
2080                                                         mode,
2081                                                         resolveLinkageError);
2082                                         if (checkresult != resolveSucceeded)
2083                                                 return (bool) checkresult;
2084                                 }
2085                         }
2086                 }
2087
2088                 /* check protected access */
2089
2090                 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
2091                 {
2092                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
2093                                         &(ref->instancetypes),
2094                                         CLASSREF_OR_CLASSINFO(referer),
2095                                         mode,
2096                                         resolveIllegalAccessError);
2097                         if (checkresult != resolveSucceeded)
2098                                 return (bool) checkresult;
2099                 }
2100         }
2101 #endif /* ENABLE_VERIFIER */
2102
2103         /* succeed */
2104         *result = mi;
2105         return true;
2106 }
2107
2108 /* resolve_method_eager ********************************************************
2109  
2110    Resolve an unresolved method reference eagerly.
2111   
2112    IN:
2113        ref..............struct containing the reference
2114    
2115    RETURN VALUE:
2116        methodinfo * to the method, or
2117            NULL if an exception has been thrown
2118    
2119 *******************************************************************************/
2120
2121 methodinfo * resolve_method_eager(unresolved_method *ref)
2122 {
2123         methodinfo *mi;
2124
2125         if (!resolve_method(ref,resolveEager,&mi))
2126                 return NULL;
2127
2128         return mi;
2129 }
2130
2131 /******************************************************************************/
2132 /* CREATING THE DATA STRUCTURES                                               */
2133 /******************************************************************************/
2134
2135 #ifdef ENABLE_VERIFIER
2136 static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
2137                                                                                                  methodinfo *refmethod,
2138                                                                                                  unresolved_subtype_set *stset,
2139                                                                                                  typeinfo *tinfo,
2140                                                                                                  utf *declaredclassname)
2141 {
2142         int count;
2143         int i;
2144
2145         assert(stset);
2146         assert(tinfo);
2147
2148 #ifdef RESOLVE_VERBOSE
2149         printf("unresolved_subtype_set_from_typeinfo\n");
2150 #ifdef TYPEINFO_DEBUG
2151         typeinfo_print(stdout,tinfo,4);
2152 #endif
2153         printf("    declared classname:");utf_fprint_printable_ascii(stdout,declaredclassname);
2154         printf("\n");
2155 #endif
2156
2157         if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
2158                 exceptions_throw_verifyerror(refmethod,
2159                                 "Invalid use of returnAddress");
2160                 return false;
2161         }
2162
2163         if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
2164                 exceptions_throw_verifyerror(refmethod,
2165                                 "Invalid use of uninitialized object");
2166                 return false;
2167         }
2168
2169         /* the nulltype is always assignable */
2170         if (TYPEINFO_IS_NULLTYPE(*tinfo))
2171                 goto empty_set;
2172
2173         /* every type is assignable to (BOOTSTRAP)java.lang.Object */
2174         if (declaredclassname == utf_java_lang_Object
2175                         && referer->classloader == NULL) /* XXX do loading constraints make the second check obsolete? */
2176         {
2177                 goto empty_set;
2178         }
2179
2180         if (tinfo->merged) {
2181                 count = tinfo->merged->count;
2182                 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
2183                 for (i=0; i<count; ++i) {
2184                         classref_or_classinfo c = tinfo->merged->list[i];
2185                         if (tinfo->dimension > 0) {
2186                                 /* a merge of array types */
2187                                 /* the merged list contains the possible _element_ types, */
2188                                 /* so we have to create array types with these elements.  */
2189                                 if (IS_CLASSREF(c)) {
2190                                         c.ref = class_get_classref_multiarray_of(tinfo->dimension,c.ref);
2191                                 }
2192                                 else {
2193                                         c.cls = class_multiarray_of(tinfo->dimension,c.cls,false);
2194                                 }
2195                         }
2196                         stset->subtyperefs[i] = c;
2197                 }
2198                 stset->subtyperefs[count].any = NULL; /* terminate */
2199         }
2200         else {
2201                 if ((IS_CLASSREF(tinfo->typeclass)
2202                                         ? tinfo->typeclass.ref->name
2203                                         : tinfo->typeclass.cls->name) == declaredclassname)
2204                 {
2205                         /* the class names are the same */
2206                     /* equality is guaranteed by the loading constraints */
2207                         goto empty_set;
2208                 }
2209                 else {
2210                         stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
2211                         stset->subtyperefs[0] = tinfo->typeclass;
2212                         stset->subtyperefs[1].any = NULL; /* terminate */
2213                 }
2214         }
2215
2216         return true;
2217
2218 empty_set:
2219         UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
2220         return true;
2221 }
2222 #endif /* ENABLE_VERIFIER */
2223
2224 /* create_unresolved_class *****************************************************
2225  
2226    Create an unresolved_class struct for the given class reference
2227   
2228    IN:
2229            refmethod........the method triggering the resolution (if any)
2230            classref.........the class reference
2231            valuetype........value type to check against the resolved class
2232                                                 may be NULL, if no typeinfo is available
2233
2234    RETURN VALUE:
2235        a pointer to a new unresolved_class struct, or
2236            NULL if an exception has been thrown
2237
2238 *******************************************************************************/
2239
2240 #ifdef ENABLE_VERIFIER
2241 unresolved_class * create_unresolved_class(methodinfo *refmethod,
2242                                                                                    constant_classref *classref,
2243                                                                                    typeinfo *valuetype)
2244 {
2245         unresolved_class *ref;
2246
2247 #ifdef RESOLVE_VERBOSE
2248         printf("create_unresolved_class\n");
2249         printf("    referer: ");utf_fprint_printable_ascii(stdout,classref->referer->name);fputc('\n',stdout);
2250         if (refmethod) {
2251                 printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
2252                 printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
2253         }
2254         printf("    name   : ");utf_fprint_printable_ascii(stdout,classref->name);fputc('\n',stdout);
2255 #endif
2256
2257         ref = NEW(unresolved_class);
2258         ref->classref = classref;
2259         ref->referermethod = refmethod;
2260
2261         if (valuetype) {
2262                 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
2263                                         &(ref->subtypeconstraints),valuetype,classref->name))
2264                         return NULL;
2265         }
2266         else {
2267                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
2268         }
2269
2270         return ref;
2271 }
2272 #endif /* ENABLE_VERIFIER */
2273
2274 /* resolve_create_unresolved_field *********************************************
2275  
2276    Create an unresolved_field struct for the given field access instruction
2277   
2278    IN:
2279        referer..........the class containing the reference
2280            refmethod........the method triggering the resolution (if any)
2281            iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
2282
2283    RETURN VALUE:
2284        a pointer to a new unresolved_field struct, or
2285            NULL if an exception has been thrown
2286
2287 *******************************************************************************/
2288
2289 unresolved_field * resolve_create_unresolved_field(classinfo *referer,
2290                                                                                                    methodinfo *refmethod,
2291                                                                                                    instruction *iptr)
2292 {
2293         unresolved_field *ref;
2294         constant_FMIref *fieldref = NULL;
2295
2296 #ifdef RESOLVE_VERBOSE
2297         printf("create_unresolved_field\n");
2298         printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
2299         printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
2300         printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
2301 #endif
2302
2303         ref = NEW(unresolved_field);
2304         ref->flags = 0;
2305         ref->referermethod = refmethod;
2306         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
2307
2308         switch (iptr->opc) {
2309                 case ICMD_PUTFIELD:
2310                         ref->flags |= RESOLVE_PUTFIELD;
2311                         break;
2312
2313                 case ICMD_PUTFIELDCONST:
2314                         ref->flags |= RESOLVE_PUTFIELD;
2315                         break;
2316
2317                 case ICMD_PUTSTATIC:
2318                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
2319                         break;
2320
2321                 case ICMD_PUTSTATICCONST:
2322                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
2323                         break;
2324
2325                 case ICMD_GETFIELD:
2326                         break;
2327
2328                 case ICMD_GETSTATIC:
2329                         ref->flags |= RESOLVE_STATIC;
2330                         break;
2331
2332 #if !defined(NDEBUG)
2333                 default:
2334                         assert(false);
2335 #endif
2336         }
2337
2338         fieldref = iptr->sx.s23.s3.fmiref;
2339
2340         assert(fieldref);
2341
2342 #ifdef RESOLVE_VERBOSE
2343 /*      printf("    class  : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout);*/
2344         printf("    name   : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
2345         printf("    desc   : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
2346         printf("    type   : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
2347         fputc('\n',stdout);
2348         /*printf("    opcode : %d %s\n",iptr->opc,icmd_names[iptr->opc]);*/
2349 #endif
2350
2351         ref->fieldref = fieldref;
2352
2353         return ref;
2354 }
2355
2356 /* resolve_constrain_unresolved_field ******************************************
2357  
2358    Record subtype constraints for a field access.
2359   
2360    IN:
2361        ref..............the unresolved_field structure of the access
2362        referer..........the class containing the reference
2363            refmethod........the method triggering the resolution (if any)
2364            instanceti.......instance typeinfo, if available
2365            valueti..........value typeinfo, if available
2366
2367    RETURN VALUE:
2368        true.............everything ok
2369            false............an exception has been thrown
2370
2371 *******************************************************************************/
2372
2373 #if defined(ENABLE_VERIFIER)
2374 bool resolve_constrain_unresolved_field(unresolved_field *ref,
2375                                                                                 classinfo *referer, 
2376                                                                                 methodinfo *refmethod,
2377                                                                             typeinfo *instanceti,
2378                                                                             typeinfo *valueti)
2379 {
2380         constant_FMIref *fieldref;
2381         int type;
2382         typeinfo tinfo;
2383         typedesc *fd;
2384
2385         assert(ref);
2386
2387         fieldref = ref->fieldref;
2388         assert(fieldref);
2389
2390 #ifdef RESOLVE_VERBOSE
2391         printf("constrain_unresolved_field\n");
2392         printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
2393         printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
2394         printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
2395 /*      printf("    class  : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout); */
2396         printf("    name   : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
2397         printf("    desc   : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
2398         printf("    type   : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
2399         fputc('\n',stdout);
2400         /*printf("    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
2401 #endif
2402
2403         assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
2404         fd = fieldref->parseddesc.fd;
2405         assert(fd);
2406
2407         /* record subtype constraints for the instance type, if any */
2408         if (instanceti) {
2409                 typeinfo *insttip;
2410
2411                 /* The instanceslot must contain a reference to a non-array type */
2412                 if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
2413                         exceptions_throw_verifyerror(refmethod, 
2414                                         "illegal instruction: field access on non-reference");
2415                         return false;
2416                 }
2417                 if (TYPEINFO_IS_ARRAY(*instanceti)) {
2418                         exceptions_throw_verifyerror(refmethod, 
2419                                         "illegal instruction: field access on array");
2420                         return false;
2421                 }
2422
2423                 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
2424                                 TYPEINFO_IS_NEWOBJECT(*instanceti))
2425                 {
2426                         /* The instruction writes a field in an uninitialized object. */
2427                         /* This is only allowed when a field of an uninitialized 'this' object is */
2428                         /* written inside an initialization method                                */
2429
2430                         classinfo *initclass;
2431                         instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
2432
2433                         if (ins != NULL) {
2434                                 exceptions_throw_verifyerror(refmethod, 
2435                                                 "accessing field of uninitialized object");
2436                                 return false;
2437                         }
2438                         /* XXX check that class of field == refmethod->class */
2439                         initclass = refmethod->class; /* XXX classrefs */
2440                         assert(initclass->state & CLASS_LOADED);
2441                         assert(initclass->state & CLASS_LINKED);
2442
2443                         typeinfo_init_classinfo(&tinfo, initclass);
2444                         insttip = &tinfo;
2445                 }
2446                 else {
2447                         insttip = instanceti;
2448                 }
2449                 if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
2450                                         &(ref->instancetypes), insttip, 
2451                                         FIELDREF_CLASSNAME(fieldref)))
2452                         return false;
2453         }
2454         else {
2455                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
2456         }
2457
2458         /* record subtype constraints for the value type, if any */
2459         type = fd->type;
2460         if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
2461                 assert(valueti);
2462                 if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
2463                                         &(ref->valueconstraints), valueti, 
2464                                         fieldref->parseddesc.fd->classref->name))
2465                         return false;
2466         }
2467         else {
2468                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
2469         }
2470
2471         return true;
2472 }
2473 #endif /* ENABLE_VERIFIER */
2474
2475 /* resolve_create_unresolved_method ********************************************
2476  
2477    Create an unresolved_method struct for the given method invocation
2478   
2479    IN:
2480        referer..........the class containing the reference
2481            refmethod........the method triggering the resolution (if any)
2482            iptr.............the INVOKE* instruction
2483
2484    RETURN VALUE:
2485        a pointer to a new unresolved_method struct, or
2486            NULL if an exception has been thrown
2487
2488 *******************************************************************************/
2489
2490 unresolved_method * resolve_create_unresolved_method(classinfo *referer,
2491                                                                                                          methodinfo *refmethod,
2492                                                                                                          constant_FMIref *methodref,
2493                                                                                                          bool invokestatic,
2494                                                                                                          bool invokespecial)
2495 {
2496         unresolved_method *ref;
2497
2498         assert(methodref);
2499
2500 #ifdef RESOLVE_VERBOSE
2501         printf("create_unresolved_method\n");
2502         printf("    referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
2503         printf("    rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
2504         printf("    rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
2505         printf("    name   : ");utf_fprint_printable_ascii(stdout,methodref->name);fputc('\n',stdout);
2506         printf("    desc   : ");utf_fprint_printable_ascii(stdout,methodref->descriptor);fputc('\n',stdout);
2507 #endif
2508
2509         /* allocate params if necessary */
2510         if (!methodref->parseddesc.md->params)
2511                 if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
2512                                         (invokestatic) ? ACC_STATIC : ACC_NONE))
2513                         return NULL;
2514
2515         /* create the data structure */
2516         ref = NEW(unresolved_method);
2517         ref->flags = ((invokestatic) ? RESOLVE_STATIC : 0)
2518                            | ((invokespecial) ? RESOLVE_SPECIAL : 0);
2519         ref->referermethod = refmethod;
2520         ref->methodref = methodref;
2521         ref->paramconstraints = NULL;
2522         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
2523
2524         return ref;
2525 }
2526
2527
2528 /* resolve_constrain_unresolved_method_instance ********************************
2529  
2530    Record subtype constraints for the instance argument of a method call.
2531   
2532    IN:
2533        ref..............the unresolved_method structure of the call
2534        referer..........the class containing the reference
2535            refmethod........the method triggering the resolution (if any)
2536            iptr.............the INVOKE* instruction
2537
2538    RETURN VALUE:
2539        true.............everything ok
2540            false............an exception has been thrown
2541
2542 *******************************************************************************/
2543
2544 #if defined(ENABLE_VERIFIER)
2545 bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
2546                                                                                                   methodinfo *refmethod,
2547                                                                                                   typeinfo *instanceti,
2548                                                                                                   bool invokespecial)
2549 {
2550         constant_FMIref   *methodref;
2551         constant_classref *instanceref;
2552         typeinfo           tinfo;
2553         typeinfo          *tip;
2554
2555         assert(ref);
2556         methodref = ref->methodref;
2557         assert(methodref);
2558
2559         /* XXX clean this up */
2560         instanceref = IS_FMIREF_RESOLVED(methodref)
2561                 ? class_get_self_classref(methodref->p.method->class)
2562                 : methodref->p.classref;
2563
2564 #ifdef RESOLVE_VERBOSE
2565         printf("resolve_constrain_unresolved_method_instance\n");
2566         printf("    rmethod: "); method_println(refmethod);
2567         printf("    mref   : "); method_methodref_println(methodref);
2568 #endif
2569
2570         /* record subtype constraints for the instance type, if any */
2571
2572         if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
2573         {   /* XXX clean up */
2574                 instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
2575                 classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
2576                                                                          : CLASSREF_OR_CLASSINFO(refmethod->class);
2577                 tip = &tinfo;
2578                 if (!typeinfo_init_class(tip, initclass))
2579                         return false;
2580         }
2581         else {
2582                 tip = instanceti;
2583         }
2584
2585         if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
2586                                 &(ref->instancetypes),tip,instanceref->name))
2587                 return false;
2588
2589         return true;
2590 }
2591 #endif /* defined(ENABLE_VERIFIER) */
2592
2593
2594 /* resolve_constrain_unresolved_method_params  *********************************
2595  
2596    Record subtype constraints for the non-instance arguments of a method call.
2597   
2598    IN:
2599        jd...............current jitdata (for looking up variables)
2600        ref..............the unresolved_method structure of the call
2601            refmethod........the method triggering the resolution (if any)
2602            iptr.............the INVOKE* instruction
2603
2604    RETURN VALUE:
2605        true.............everything ok
2606            false............an exception has been thrown
2607
2608 *******************************************************************************/
2609
2610 #if defined(ENABLE_VERIFIER)
2611 bool resolve_constrain_unresolved_method_params(jitdata *jd,
2612                                                                                                 unresolved_method *ref,
2613                                                                                                 methodinfo *refmethod,
2614                                                                                                 instruction *iptr)
2615 {
2616         constant_FMIref *methodref;
2617         varinfo *param;
2618         methoddesc *md;
2619         int i,j;
2620         int type;
2621         int instancecount;
2622
2623         assert(ref);
2624         methodref = ref->methodref;
2625         assert(methodref);
2626         md = methodref->parseddesc.md;
2627         assert(md);
2628         assert(md->params != NULL);
2629
2630 #ifdef RESOLVE_VERBOSE
2631         printf("resolve_constrain_unresolved_method_params\n");
2632         printf("    rmethod: "); method_println(refmethod);
2633         printf("    mref   : "); method_methodref_println(methodref);
2634         /*printf("    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
2635 #endif
2636
2637         instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
2638
2639         /* record subtype constraints for the parameter types, if any */
2640
2641         for (i=md->paramcount-1-instancecount; i>=0; --i) {
2642                 param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
2643                 type = md->paramtypes[i+instancecount].type;
2644
2645                 assert(param);
2646                 assert(type == param->type);
2647
2648                 if (type == TYPE_ADR) {
2649                         if (!ref->paramconstraints) {
2650                                 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
2651                                 for (j=md->paramcount-1-instancecount; j>i; --j)
2652                                         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
2653                         }
2654                         assert(ref->paramconstraints);
2655                         if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
2656                                                 ref->paramconstraints + i,&(param->typeinfo),
2657                                                 md->paramtypes[i+instancecount].classref->name))
2658                                 return false;
2659                 }
2660                 else {
2661                         if (ref->paramconstraints)
2662                                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
2663                 }
2664         }
2665
2666         return true;
2667 }
2668 #endif /* ENABLE_VERIFIER */
2669
2670
2671 /* resolve_constrain_unresolved_method_params_stackbased ***********************
2672  
2673    Record subtype constraints for the non-instance arguments of a method call.
2674   
2675    IN:
2676        ref..............the unresolved_method structure of the call
2677            refmethod........the method triggering the resolution (if any)
2678            stack............TOS before the INVOKE instruction
2679
2680    RETURN VALUE:
2681        true.............everything ok
2682            false............an exception has been thrown
2683
2684 *******************************************************************************/
2685
2686 #if defined(ENABLE_VERIFIER)
2687 bool resolve_constrain_unresolved_method_params_stackbased(
2688                 unresolved_method *ref,
2689                 methodinfo *refmethod,
2690                 typedescriptor *stack)
2691 {
2692         constant_FMIref *methodref;
2693         typedescriptor *param;
2694         methoddesc *md;
2695         int i,j;
2696         int type;
2697         int instancecount;
2698
2699         assert(ref);
2700         methodref = ref->methodref;
2701         assert(methodref);
2702         md = methodref->parseddesc.md;
2703         assert(md);
2704         assert(md->params != NULL);
2705
2706 #ifdef RESOLVE_VERBOSE
2707         printf("resolve_constrain_unresolved_method_params_stackbased\n");
2708         printf("    rmethod: "); method_println(refmethod);
2709         printf("    mref   : "); method_methodref_println(methodref);
2710 #endif
2711
2712         instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
2713
2714         /* record subtype constraints for the parameter types, if any */
2715
2716         param = stack - (md->paramslots - 1 - instancecount);
2717
2718         for (i = instancecount; i < md->paramcount; ++i) {
2719                 type = md->paramtypes[i].type;
2720
2721                 assert(type == param->type);
2722
2723                 if (type == TYPE_ADR) {
2724                         if (!ref->paramconstraints) {
2725                                 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
2726                                 for (j = 0; j < i - instancecount; ++j)
2727                                         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
2728                         }
2729                         assert(ref->paramconstraints);
2730                         if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
2731                                                 ref->paramconstraints + i - instancecount,&(param->typeinfo),
2732                                                 md->paramtypes[i].classref->name))
2733                                 return false;
2734                 }
2735                 else {
2736                         if (ref->paramconstraints)
2737                                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
2738                 }
2739
2740                 param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
2741         }
2742
2743         return true;
2744 }
2745 #endif /* ENABLE_VERIFIER */
2746
2747
2748 /******************************************************************************/
2749 /* FREEING MEMORY                                                             */
2750 /******************************************************************************/
2751
2752 #ifdef ENABLE_VERIFIER
2753 inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
2754 {
2755         if (list) {
2756                 classref_or_classinfo *p = list;
2757
2758                 /* this is silly. we *only* need to count the elements for MFREE */
2759                 while ((p++)->any)
2760                         ;
2761                 MFREE(list,classref_or_classinfo,(p - list));
2762         }
2763 }
2764 #endif /* ENABLE_VERIFIER */
2765
2766 /* unresolved_class_free *******************************************************
2767  
2768    Free the memory used by an unresolved_class
2769   
2770    IN:
2771        ref..............the unresolved_class
2772
2773 *******************************************************************************/
2774
2775 void unresolved_class_free(unresolved_class *ref)
2776 {
2777         assert(ref);
2778
2779 #ifdef ENABLE_VERIFIER
2780         unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
2781 #endif
2782         FREE(ref,unresolved_class);
2783 }
2784
2785 /* unresolved_field_free *******************************************************
2786  
2787    Free the memory used by an unresolved_field
2788   
2789    IN:
2790        ref..............the unresolved_field
2791
2792 *******************************************************************************/
2793
2794 void unresolved_field_free(unresolved_field *ref)
2795 {
2796         assert(ref);
2797
2798 #ifdef ENABLE_VERIFIER
2799         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
2800         unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
2801 #endif
2802         FREE(ref,unresolved_field);
2803 }
2804
2805 /* unresolved_method_free ******************************************************
2806  
2807    Free the memory used by an unresolved_method
2808   
2809    IN:
2810        ref..............the unresolved_method
2811
2812 *******************************************************************************/
2813
2814 void unresolved_method_free(unresolved_method *ref)
2815 {
2816         assert(ref);
2817
2818 #ifdef ENABLE_VERIFIER
2819         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
2820         if (ref->paramconstraints) {
2821                 int i;
2822                 int count = ref->methodref->parseddesc.md->paramcount;
2823
2824                 for (i=0; i<count; ++i)
2825                         unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
2826                 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
2827         }
2828 #endif
2829         FREE(ref,unresolved_method);
2830 }
2831
2832 /******************************************************************************/
2833 /* DEBUG DUMPS                                                                */
2834 /******************************************************************************/
2835
2836 #if !defined(NDEBUG)
2837
2838 /* unresolved_subtype_set_debug_dump *******************************************
2839  
2840    Print debug info for unresolved_subtype_set to stream
2841   
2842    IN:
2843        stset............the unresolved_subtype_set
2844            file.............the stream
2845
2846 *******************************************************************************/
2847
2848 void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
2849 {
2850         classref_or_classinfo *p;
2851
2852         if (SUBTYPESET_IS_EMPTY(*stset)) {
2853                 fprintf(file,"        (empty)\n");
2854         }
2855         else {
2856                 p = stset->subtyperefs;
2857                 for (;p->any; ++p) {
2858                         if (IS_CLASSREF(*p)) {
2859                                 fprintf(file,"        ref: ");
2860                                 utf_fprint_printable_ascii(file,p->ref->name);
2861                         }
2862                         else {
2863                                 fprintf(file,"        cls: ");
2864                                 utf_fprint_printable_ascii(file,p->cls->name);
2865                         }
2866                         fputc('\n',file);
2867                 }
2868         }
2869 }
2870
2871 /* unresolved_class_debug_dump *************************************************
2872  
2873    Print debug info for unresolved_class to stream
2874   
2875    IN:
2876        ref..............the unresolved_class
2877            file.............the stream
2878
2879 *******************************************************************************/
2880
2881 void unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
2882 {
2883         fprintf(file,"unresolved_class(%p):\n",(void *)ref);
2884         if (ref) {
2885                 fprintf(file,"    referer   : ");
2886                 utf_fprint_printable_ascii(file,ref->classref->referer->name); fputc('\n',file);
2887                 fprintf(file,"    refmethod : ");
2888                 utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
2889                 fprintf(file,"    refmethodd: ");
2890                 utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
2891                 fprintf(file,"    classname : ");
2892                 utf_fprint_printable_ascii(file,ref->classref->name); fputc('\n',file);
2893                 fprintf(file,"    subtypeconstraints:\n");
2894                 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
2895         }
2896 }
2897
2898 /* unresolved_field_debug_dump *************************************************
2899  
2900    Print debug info for unresolved_field to stream
2901   
2902    IN:
2903        ref..............the unresolved_field
2904            file.............the stream
2905
2906 *******************************************************************************/
2907
2908 void unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
2909 {
2910         fprintf(file,"unresolved_field(%p):\n",(void *)ref);
2911         if (ref) {
2912                 fprintf(file,"    referer   : ");
2913                 utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
2914                 fprintf(file,"    refmethod : ");
2915                 utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
2916                 fprintf(file,"    refmethodd: ");
2917                 utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
2918                 fprintf(file,"    classname : ");
2919                 utf_fprint_printable_ascii(file,FIELDREF_CLASSNAME(ref->fieldref)); fputc('\n',file);
2920                 fprintf(file,"    name      : ");
2921                 utf_fprint_printable_ascii(file,ref->fieldref->name); fputc('\n',file);
2922                 fprintf(file,"    descriptor: ");
2923                 utf_fprint_printable_ascii(file,ref->fieldref->descriptor); fputc('\n',file);
2924                 fprintf(file,"    parseddesc: ");
2925                 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
2926                 fprintf(file,"    flags     : %04x\n",ref->flags);
2927                 fprintf(file,"    instancetypes:\n");
2928                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
2929                 fprintf(file,"    valueconstraints:\n");
2930                 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
2931         }
2932 }
2933
2934 /* unresolved_method_debug_dump ************************************************
2935  
2936    Print debug info for unresolved_method to stream
2937   
2938    IN:
2939        ref..............the unresolved_method
2940            file.............the stream
2941
2942 *******************************************************************************/
2943
2944 void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
2945 {
2946         int i;
2947
2948         fprintf(file,"unresolved_method(%p):\n",(void *)ref);
2949         if (ref) {
2950                 fprintf(file,"    referer   : ");
2951                 utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
2952                 fprintf(file,"    refmethod : ");
2953                 utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
2954                 fprintf(file,"    refmethodd: ");
2955                 utf_fprint_printable_ascii(file,ref->referermethod->descriptor); fputc('\n',file);
2956                 fprintf(file,"    classname : ");
2957                 utf_fprint_printable_ascii(file,METHODREF_CLASSNAME(ref->methodref)); fputc('\n',file);
2958                 fprintf(file,"    name      : ");
2959                 utf_fprint_printable_ascii(file,ref->methodref->name); fputc('\n',file);
2960                 fprintf(file,"    descriptor: ");
2961                 utf_fprint_printable_ascii(file,ref->methodref->descriptor); fputc('\n',file);
2962                 fprintf(file,"    parseddesc: ");
2963                 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
2964                 fprintf(file,"    flags     : %04x\n",ref->flags);
2965                 fprintf(file,"    instancetypes:\n");
2966                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
2967                 fprintf(file,"    paramconstraints:\n");
2968                 if (ref->paramconstraints) {
2969                         for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
2970                                 fprintf(file,"      param %d:\n",i);
2971                                 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
2972                         }
2973                 }
2974                 else {
2975                         fprintf(file,"      (empty)\n");
2976                 }
2977         }
2978 }
2979 #endif /* !defined(NDEBUG) */
2980
2981 /*
2982  * These are local overrides for various environment variables in Emacs.
2983  * Please do not remove this and leave it at the end of the file, where
2984  * Emacs will automagically detect them.
2985  * ---------------------------------------------------------------------
2986  * Local variables:
2987  * mode: c
2988  * indent-tabs-mode: t
2989  * c-basic-offset: 4
2990  * tab-width: 4
2991  * End:
2992  * vim:noexpandtab:sw=4:ts=4:
2993  */
2994