* src/vm/resolve.c (resolve_method_lazy): Turn INVOKEVIRTUAL into
[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 4857 2006-04-28 11:24:39Z 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         fprintf(stderr,"resolve_class_from_name(");
120         utf_fprint(stderr,referer->name);
121         fprintf(stderr,",%p,",referer->classloader);
122         utf_fprint(stderr,classname);
123         fprintf(stderr,",%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         fprintf(stderr,"    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                 fprintf(stderr,"    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         fprintf(stderr,"    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_strlen(cls->name) + utf_strlen(referer->name) + 100;
197                 message = MNEW(char,msglen);
198                 strcpy(message,"class is not accessible (");
199                 utf_sprint_classname(message+strlen(message),cls->name);
200                 strcat(message," from ");
201                 utf_sprint_classname(message+strlen(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         fprintf(stderr,"    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         fprintf(stderr,"resolve_classref_or_classinfo(");
308         utf_fprint(stderr,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
309         fprintf(stderr,",%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 resolved 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         fprintf(stderr,"resolve_class_from_typedesc(");
387         descriptor_debug_print_typedesc(stderr,d);
388         fprintf(stderr,",%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         fprintf(stderr,"    result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\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                 msglen = utf_strlen(subclass->name) + utf_strlen(CLASSREF_OR_CLASSINFO_NAME(supertype)) + 200;
523                 message = MNEW(char,msglen);
524                 strcpy(message,(error == resolveIllegalAccessError) ?
525                                 "illegal access to protected member ("
526                                 : "subtype constraint violated (");
527                 utf_sprint_classname(message+strlen(message),subclass->name);
528                 strcat(message," is not a subclass of ");
529                 utf_sprint_classname(message+strlen(message),CLASSREF_OR_CLASSINFO_NAME(supertype));
530                 strcat(message,")");
531                 if (error == resolveIllegalAccessError)
532                         *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
533                 else
534                         *exceptionptr = exceptions_new_linkageerror(message,NULL);
535                 MFREE(message,char,msglen);
536                 return resolveFailed; /* exception */
537         }
538
539         /* everything ok */
540
541         return resolveSucceeded;
542 }
543 #endif /* defined(ENABLE_VERIFIER) */
544
545 /* resolve_lazy_subtype_checks *************************************************
546  
547    Resolve the types to check lazily and perform subtype checks
548   
549    IN:
550        refmethod........the method triggering the resolution
551        subtinfo.........the typeinfo containing the subtypes
552        supertype........the supertype to test againgst
553            mode.............mode of resolution:
554                             resolveLazy...only resolve if it does not
555                                           require loading classes
556                             resolveEager..load classes if necessary
557        error............which type of exception to throw if
558                         the test fails. May be:
559                             resolveLinkageError, or
560                             resolveIllegalAccessError
561                                                 IMPORTANT: If error==resolveIllegalAccessError,
562                                                 then array types in the set are skipped.
563
564    RETURN VALUE:
565        resolveSucceeded.....the check succeeded
566        resolveDeferred......the check could not be performed due to
567                                 unresolved types
568            resolveFailed........the check failed, an exception has been thrown.
569    
570    NOTE:
571        The references in the set are resolved first, so any
572        exception which may occurr during resolution may
573        be thrown by this function.
574    
575 *******************************************************************************/
576
577 #if defined(ENABLE_VERIFIER)
578 static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
579                                                                                                         typeinfo *subtinfo,
580                                                                                                         classref_or_classinfo supertype,
581                                                                                                         resolve_err_t error)
582 {
583         int count;
584         int i;
585         resolve_result_t result;
586
587         assert(refmethod);
588         assert(subtinfo);
589         assert(supertype.any);
590         assert(error == resolveLinkageError || error == resolveIllegalAccessError);
591
592         /* returnAddresses are illegal here */
593
594         if (TYPEINFO_IS_PRIMITIVE(*subtinfo)) {
595                 *exceptionptr = new_verifyerror(refmethod,
596                                 "Invalid use of returnAddress");
597                 return resolveFailed;
598         }
599
600         /* uninitialized objects are illegal here */
601
602         if (TYPEINFO_IS_NEWOBJECT(*subtinfo)) {
603                 *exceptionptr = new_verifyerror(refmethod,
604                                 "Invalid use of uninitialized object");
605                 return resolveFailed;
606         }
607
608         /* the nulltype is always assignable */
609
610         if (TYPEINFO_IS_NULLTYPE(*subtinfo))
611                 return resolveSucceeded;
612
613         /* every type is assignable to (BOOTSTRAP)java.lang.Object */
614
615         if (supertype.cls == class_java_lang_Object
616                 || (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
617                         && refmethod->class->classloader == NULL))
618         {
619                 return resolveSucceeded;
620         }
621
622         if (subtinfo->merged) {
623
624                 /* for a merged type we have to do a series of checks */
625
626                 count = subtinfo->merged->count;
627                 for (i=0; i<count; ++i) {
628                         classref_or_classinfo c = subtinfo->merged->list[i];
629                         if (subtinfo->dimension > 0) {
630                                 /* a merge of array types */
631                                 /* the merged list contains the possible _element_ types, */
632                                 /* so we have to create array types with these elements.  */
633                                 if (IS_CLASSREF(c)) {
634                                         c.ref = class_get_classref_multiarray_of(subtinfo->dimension,c.ref);
635                                 }
636                                 else {
637                                         c.cls = class_multiarray_of(subtinfo->dimension,c.cls,false);
638                                 }
639                         }
640
641                         /* do the subtype check against the type c */
642
643                         result = resolve_subtype_check(refmethod,c,supertype,resolveLazy,error);
644                         if (result != resolveSucceeded)
645                                 return result;
646                 }
647         }
648         else {
649
650                 /* a single type, this is the common case, hopefully */
651
652                 if (CLASSREF_OR_CLASSINFO_NAME(subtinfo->typeclass)
653                         == CLASSREF_OR_CLASSINFO_NAME(supertype))
654                 {
655                         /* the class names are the same */
656                     /* equality is guaranteed by the loading constraints */
657                         return resolveSucceeded;
658                 }
659                 else {
660
661                         /* some other type name, try to perform the check lazily */
662
663                         return resolve_subtype_check(refmethod,
664                                                                                  subtinfo->typeclass,supertype,
665                                                                                  resolveLazy,
666                                                                                  error);
667                 }
668         }
669
670         /* everything ok */
671         return resolveSucceeded;
672 }
673 #endif /* defined(ENABLE_VERIFIER) */
674
675 /* resolve_and_check_subtype_set ***********************************************
676  
677    Resolve the references in the given set and test subtype relationships
678   
679    IN:
680        refmethod........the method triggering the resolution
681        ref..............a set of class/interface references
682                         (may be empty)
683        typeref..........the type to test against the set
684        mode.............mode of resolution:
685                             resolveLazy...only resolve if it does not
686                                           require loading classes
687                             resolveEager..load classes if necessary
688        error............which type of exception to throw if
689                         the test fails. May be:
690                             resolveLinkageError, or
691                             resolveIllegalAccessError
692                                                 IMPORTANT: If error==resolveIllegalAccessError,
693                                                 then array types in the set are skipped.
694
695    RETURN VALUE:
696        resolveSucceeded.....the check succeeded
697        resolveDeferred......the check could not be performed due to
698                                 unresolved types. (This can only happen if
699                                                         mode == resolveLazy.)
700            resolveFailed........the check failed, an exception has been thrown.
701    
702    NOTE:
703        The references in the set are resolved first, so any
704        exception which may occurr during resolution may
705        be thrown by this function.
706    
707 *******************************************************************************/
708
709 #if defined(ENABLE_VERIFIER)
710 static resolve_result_t resolve_and_check_subtype_set(methodinfo *refmethod,
711                                                                           unresolved_subtype_set *ref,
712                                                                           classref_or_classinfo typeref,
713                                                                           resolve_mode_t mode,
714                                                                           resolve_err_t error)
715 {
716         classref_or_classinfo *setp;
717         typecheck_result checkresult;
718
719         assert(refmethod);
720         assert(ref);
721         assert(typeref.any);
722         assert(mode == resolveLazy || mode == resolveEager);
723         assert(error == resolveLinkageError || error == resolveIllegalAccessError);
724
725         setp = ref->subtyperefs;
726
727         /* an empty set of tests always succeeds */
728         if (!setp || !setp->any) {
729                 return resolveSucceeded;
730         }
731
732         /* first resolve the type if necessary */
733         if (!resolve_classref_or_classinfo(refmethod,typeref,mode,false,true,&(typeref.cls)))
734                 return resolveFailed; /* exception */
735         if (!typeref.cls)
736                 return resolveDeferred; /* be lazy */
737
738         assert(typeref.cls->state & CLASS_LINKED);
739
740         /* iterate over the set members */
741
742         for (; setp->any; ++setp) {
743                 checkresult = resolve_subtype_check(refmethod,*setp,typeref,mode,error);
744                 if (checkresult != resolveSucceeded)
745                         return checkresult;
746         }
747
748         /* check succeeds */
749         return resolveSucceeded;
750 }
751 #endif /* defined(ENABLE_VERIFIER) */
752
753 /******************************************************************************/
754 /* CLASS RESOLUTION                                                           */
755 /******************************************************************************/
756
757 /* resolve_class ***************************************************************
758  
759    Resolve an unresolved class reference. The class is also linked.
760   
761    IN:
762        ref..............struct containing the reference
763        mode.............mode of resolution:
764                             resolveLazy...only resolve if it does not
765                                           require loading classes
766                             resolveEager..load classes if necessary
767            checkaccess......if true, access rights to the class are checked
768    
769    OUT:
770        *result..........set to the result of resolution, or to NULL if
771                         the reference has not been resolved
772                         In the case of an exception, *result is
773                         guaranteed to be set to NULL.
774   
775    RETURN VALUE:
776        true.............everything ok 
777                         (*result may still be NULL for resolveLazy)
778        false............an exception has been thrown
779    
780 *******************************************************************************/
781
782 #ifdef ENABLE_VERIFIER
783 bool resolve_class(unresolved_class *ref,
784                                    resolve_mode_t mode,
785                                    bool checkaccess,
786                                    classinfo **result)
787 {
788         classinfo *cls;
789         resolve_result_t checkresult;
790         
791         assert(ref);
792         assert(result);
793         assert(mode == resolveLazy || mode == resolveEager);
794
795         *result = NULL;
796
797 #ifdef RESOLVE_VERBOSE
798         unresolved_class_debug_dump(ref,stderr);
799 #endif
800
801         /* first we must resolve the class */
802         if (!resolve_classref(ref->referermethod,
803                                               ref->classref,mode,checkaccess,true,&cls))
804         {
805                 /* the class reference could not be resolved */
806                 return false; /* exception */
807         }
808         if (!cls)
809                 return true; /* be lazy */
810
811         assert(cls);
812         assert((cls->state & CLASS_LOADED) && (cls->state & CLASS_LINKED));
813
814         /* now we check the subtype constraints */
815         
816         checkresult = resolve_and_check_subtype_set(ref->referermethod,
817                                                                            &(ref->subtypeconstraints),
818                                                                            CLASSREF_OR_CLASSINFO(cls),
819                                                                            mode,
820                                                                            resolveLinkageError);
821         if (checkresult != resolveSucceeded)
822                 return (bool) checkresult;
823
824         /* succeed */
825         *result = cls;
826         return true;
827 }
828 #endif /* ENABLE_VERIFIER */
829
830 /* resolve_classref_eager ******************************************************
831  
832    Resolve an unresolved class reference eagerly. The class is also linked and
833    access rights to the class are checked.
834   
835    IN:
836        ref..............constant_classref to the class
837    
838    RETURN VALUE:
839        classinfo * to the class, or
840            NULL if an exception has been thrown
841    
842 *******************************************************************************/
843
844 classinfo * resolve_classref_eager(constant_classref *ref)
845 {
846         classinfo *c;
847
848         if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
849                 return NULL;
850
851         return c;
852 }
853
854 /* resolve_classref_eager_nonabstract ******************************************
855  
856    Resolve an unresolved class reference eagerly. The class is also linked and
857    access rights to the class are checked. A check is performed that the class
858    is not abstract.
859   
860    IN:
861        ref..............constant_classref to the class
862    
863    RETURN VALUE:
864        classinfo * to the class, or
865            NULL if an exception has been thrown
866    
867 *******************************************************************************/
868
869 classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
870 {
871         classinfo *c;
872
873         if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
874                 return NULL;
875
876         /* ensure that the class is not abstract */
877
878         if (c->flags & ACC_ABSTRACT) {
879                 *exceptionptr = new_verifyerror(NULL,"creating instance of abstract class");
880                 return NULL;
881         }
882
883         return c;
884 }
885
886 /* resolve_class_eager *********************************************************
887  
888    Resolve an unresolved class reference eagerly. The class is also linked and
889    access rights to the class are checked.
890   
891    IN:
892        ref..............struct containing the reference
893    
894    RETURN VALUE:
895        classinfo * to the class, or
896            NULL if an exception has been thrown
897    
898 *******************************************************************************/
899
900 #ifdef ENABLE_VERIFIER
901 classinfo * resolve_class_eager(unresolved_class *ref)
902 {
903         classinfo *c;
904
905         if (!resolve_class(ref,resolveEager,true,&c))
906                 return NULL;
907
908         return c;
909 }
910 #endif /* ENABLE_VERIFIER */
911
912 /******************************************************************************/
913 /* FIELD RESOLUTION                                                           */
914 /******************************************************************************/
915
916 /* resolve_field_verifier_checks ***********************************************
917  
918    Do the verifier checks necessary after field has been resolved.
919   
920    IN:
921        refmethod........the method containing the reference
922            fieldref.........the field reference
923            container........the class where the field was found
924            fi...............the fieldinfo of the resolved field
925            opc..............opcode of the {GET,PUT}{STATIC,FIELD} instruction
926   
927    RETURN VALUE:
928        resolveSucceeded....everything ok
929            resolveDeferred.....tests could not be done, have been deferred
930        resolveFailed.......exception has been thrown
931    
932 *******************************************************************************/
933
934 #if defined(ENABLE_VERIFIER)
935 resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
936                                                                                            constant_FMIref *fieldref,
937                                                                                            classinfo *container,
938                                                                                            fieldinfo *fi,
939                                                                                            s4 opc,
940                                                                                            stackptr curstack)
941 {
942         classinfo *declarer;
943         classinfo *referer;
944         resolve_result_t result;
945         bool isstatic = false;
946         bool isput = false;
947         stackelement *instanceslot = NULL;
948         stackelement *valueslot = NULL;
949         constant_classref *fieldtyperef;
950
951         assert(refmethod);
952         assert(fieldref);
953         assert(container);
954         assert(fi);
955
956         /* get the classinfos and the field type */
957
958         referer = refmethod->class;
959         assert(referer);
960
961         declarer = fi->class;
962         assert(declarer);
963         assert(referer->state & CLASS_LINKED);
964
965         fieldtyperef = fieldref->parseddesc.fd->classref;
966
967         /* get opcode dependent values */
968
969         switch (opc) {
970                 case ICMD_PUTFIELD:
971                         isput = true;
972                         if (curstack) {
973                                 valueslot = curstack;
974                                 instanceslot = curstack->prev;
975                         }
976                         break;
977
978                 case ICMD_PUTFIELDCONST:
979                         isput = true;
980                         instanceslot = curstack;
981                         break;
982
983                 case ICMD_PUTSTATIC:
984                         isput = true;
985                         isstatic = true;
986                         valueslot = curstack;
987                         break;
988
989                 case ICMD_PUTSTATICCONST:
990                         isput = true;
991                         isstatic = true;
992                         break;
993
994                 case ICMD_GETFIELD:
995                         instanceslot = curstack;
996                         break;
997
998                 case ICMD_GETSTATIC:
999                         isstatic = true;
1000                         break;
1001         }
1002
1003         /* check static */
1004
1005 #if true != 1
1006 #error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
1007 #endif
1008
1009         if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
1010                 /* a static field is accessed via an instance, or vice versa */
1011                 *exceptionptr =
1012                         new_exception_message(string_java_lang_IncompatibleClassChangeError,
1013                                 (fi->flags & ACC_STATIC) ? "static field accessed via instance"
1014                                                          : "instance field  accessed without instance");
1015                 return resolveFailed;
1016         }
1017
1018         /* check access rights */
1019
1020         if (!access_is_accessible_member(referer,declarer,fi->flags)) {
1021                 int msglen;
1022                 char *message;
1023
1024                 msglen = utf_strlen(declarer->name) + utf_strlen(fi->name) + utf_strlen(referer->name) + 100;
1025                 message = MNEW(char,msglen);
1026                 strcpy(message,"field is not accessible (");
1027                 utf_sprint_classname(message+strlen(message),declarer->name);
1028                 strcat(message,".");
1029                 utf_sprint(message+strlen(message),fi->name);
1030                 strcat(message," from ");
1031                 utf_sprint_classname(message+strlen(message),referer->name);
1032                 strcat(message,")");
1033                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
1034                 MFREE(message,char,msglen);
1035                 return resolveFailed; /* exception */
1036         }
1037
1038         /* for non-static methods we have to check the constraints on the         */
1039         /* instance type                                                          */
1040
1041         if (instanceslot) {
1042                 typeinfo *insttip;
1043                 typeinfo tinfo;
1044
1045                 /* The instanceslot must contain a reference to a non-array type */
1046
1047                 assert(instanceslot->type == TYPE_ADR); /* checked earlier */
1048
1049                 if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
1050                         *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on non-reference");
1051                         return resolveFailed;
1052                 }
1053                 if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
1054                         *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
1055                         return resolveFailed;
1056                 }
1057
1058                 if (isput && TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1059                 {
1060                         /* The instruction writes a field in an uninitialized object. */
1061                         /* This is only allowed when a field of an uninitialized 'this' object is */
1062                         /* written inside an initialization method                                */
1063
1064                         classinfo *initclass;
1065                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1066
1067                         if (ins != NULL) {
1068                                 *exceptionptr = new_verifyerror(refmethod,"accessing field of uninitialized object");
1069                                 return resolveFailed;
1070                         }
1071
1072                         /* XXX check that class of field == refmethod->class */
1073                         initclass = referer; /* XXX classrefs */
1074                         assert(initclass->state & CLASS_LINKED);
1075
1076                         typeinfo_init_classinfo(&tinfo,initclass);
1077                         insttip = &tinfo;
1078                 }
1079                 else {
1080                         insttip = &(instanceslot->typeinfo);
1081                 }
1082
1083                 result = resolve_lazy_subtype_checks(refmethod,
1084                                 insttip,
1085                                 CLASSREF_OR_CLASSINFO(container),
1086                                 resolveLinkageError);
1087                 if (result != resolveSucceeded)
1088                         return result;
1089
1090                 /* check protected access */
1091
1092                 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
1093                 {
1094                         result = resolve_lazy_subtype_checks(refmethod,
1095                                         &(instanceslot->typeinfo),
1096                                         CLASSREF_OR_CLASSINFO(referer),
1097                                         resolveIllegalAccessError);
1098                         if (result != resolveSucceeded)
1099                                 return result;
1100                 }
1101
1102         }
1103
1104         /* for PUT* instructions we have to check the constraints on the value type */
1105
1106         if (valueslot && valueslot->type == TYPE_ADR) {
1107                 assert(fieldtyperef);
1108
1109                 /* check subtype constraints */
1110                 result = resolve_lazy_subtype_checks(refmethod,
1111                                 &(valueslot->typeinfo),
1112                                 CLASSREF_OR_CLASSINFO(fieldtyperef),
1113                                 resolveLinkageError);
1114
1115                 if (result != resolveSucceeded)
1116                         return result;
1117         }
1118
1119         /* impose loading constraint on field type */
1120
1121         if (fi->type == TYPE_ADR) {
1122                 assert(fieldtyperef);
1123                 if (!classcache_add_constraint(declarer->classloader,
1124                                                                            referer->classloader,
1125                                                                            fieldtyperef->name))
1126                         return resolveFailed;
1127         }
1128
1129         /* XXX impose loading constraing on instance? */
1130
1131         /* everything ok */
1132         return resolveSucceeded;
1133 }
1134 #endif /* defined(ENABLE_VERIFIER) */
1135
1136 /* resolve_field_lazy **********************************************************
1137  
1138    Resolve an unresolved field reference lazily
1139   
1140    IN:
1141        iptr.............instruction containing the field reference
1142        curstack.........instack of the instruction
1143            refmethod........the referer method
1144   
1145    RETURN VALUE:
1146        resolveSucceeded.....the reference has been resolved
1147        resolveDeferred......the resolving could not be performed lazily
1148            resolveFailed........resolving failed, an exception has been thrown.
1149    
1150 *******************************************************************************/
1151
1152 resolve_result_t resolve_field_lazy(instruction *iptr,stackptr curstack,
1153                                                                         methodinfo *refmethod)
1154 {
1155         classinfo *referer;
1156         classinfo *container;
1157         fieldinfo *fi;
1158         constant_FMIref *fieldref;
1159         resolve_result_t result;
1160
1161         assert(iptr);
1162         assert(refmethod);
1163
1164         /* the class containing the reference */
1165
1166         referer = refmethod->class;
1167         assert(referer);
1168
1169         /* get the field reference */
1170
1171         if (iptr->opc == ICMD_PUTFIELDCONST || iptr->opc == ICMD_PUTSTATICCONST)
1172                 INSTRUCTION_GET_FIELDREF(iptr + 1,fieldref);
1173         else
1174                 INSTRUCTION_GET_FIELDREF(iptr,fieldref);
1175
1176         /* check if the field itself is already resolved */
1177
1178         if (IS_FMIREF_RESOLVED(fieldref)) {
1179                 fi = fieldref->p.field;
1180                 container = fi->class;
1181                 goto resolved_the_field;
1182         }
1183
1184         /* first we must resolve the class containg the field */
1185
1186         /* XXX can/may lazyResolving trigger linking? */
1187
1188         if (!resolve_class_from_name(referer,refmethod,
1189                            fieldref->p.classref->name,resolveLazy,true,true,&container))
1190         {
1191                 /* the class reference could not be resolved */
1192                 return resolveFailed; /* exception */
1193         }
1194         if (!container)
1195                 return resolveDeferred; /* be lazy */
1196
1197         assert(container->state & CLASS_LINKED);
1198
1199         /* now we must find the declaration of the field in `container`
1200          * or one of its superclasses */
1201
1202         fi = class_resolvefield(container,
1203                                                         fieldref->name,fieldref->descriptor,
1204                                                         referer,true);
1205         if (!fi) {
1206                 /* The field does not exist. But since we were called lazily, */
1207                 /* this error must not be reported now. (It will be reported   */
1208                 /* if eager resolving of this field is ever tried.)           */
1209
1210                 *exceptionptr = NULL;
1211                 return resolveDeferred; /* be lazy */
1212         }
1213
1214         /* cache the result of the resolution */
1215
1216         fieldref->p.field = fi;
1217
1218 resolved_the_field:
1219
1220 #if defined(ENABLE_VERIFIER)
1221         if (opt_verify) {
1222                 result = resolve_field_verifier_checks(refmethod,fieldref,container,
1223                                                                                            fi,
1224                                                                                            iptr->opc,
1225                                                                                            curstack);
1226
1227                 if (result != resolveSucceeded)
1228                         return result;
1229         }
1230 #endif /* defined(ENABLE_VERIFIER) */
1231
1232         /* everything ok */
1233         return resolveSucceeded;
1234 }
1235
1236 /* resolve_field ***************************************************************
1237  
1238    Resolve an unresolved field reference
1239   
1240    IN:
1241        ref..............struct containing the reference
1242        mode.............mode of resolution:
1243                             resolveLazy...only resolve if it does not
1244                                           require loading classes
1245                             resolveEager..load classes if necessary
1246   
1247    OUT:
1248        *result..........set to the result of resolution, or to NULL if
1249                         the reference has not been resolved
1250                         In the case of an exception, *result is
1251                         guaranteed to be set to NULL.
1252   
1253    RETURN VALUE:
1254        true.............everything ok 
1255                         (*result may still be NULL for resolveLazy)
1256        false............an exception has been thrown
1257    
1258 *******************************************************************************/
1259
1260 bool resolve_field(unresolved_field *ref,
1261                                    resolve_mode_t mode,
1262                                    fieldinfo **result)
1263 {
1264         classinfo *referer;
1265         classinfo *container;
1266         classinfo *declarer;
1267         constant_classref *fieldtyperef;
1268         fieldinfo *fi;
1269         resolve_result_t checkresult;
1270
1271         assert(ref);
1272         assert(result);
1273         assert(mode == resolveLazy || mode == resolveEager);
1274
1275         *result = NULL;
1276
1277 #ifdef RESOLVE_VERBOSE
1278         unresolved_field_debug_dump(ref,stderr);
1279 #endif
1280
1281         /* the class containing the reference */
1282
1283         referer = ref->referermethod->class;
1284         assert(referer);
1285
1286         /* check if the field itself is already resolved */
1287         if (IS_FMIREF_RESOLVED(ref->fieldref)) {
1288                 fi = ref->fieldref->p.field;
1289                 container = fi->class;
1290                 goto resolved_the_field;
1291         }
1292
1293         /* first we must resolve the class containg the field */
1294         if (!resolve_class_from_name(referer,ref->referermethod,
1295                                            ref->fieldref->p.classref->name,mode,true,true,&container))
1296         {
1297                 /* the class reference could not be resolved */
1298                 return false; /* exception */
1299         }
1300         if (!container)
1301                 return true; /* be lazy */
1302
1303         assert(container);
1304         assert(container->state & CLASS_LOADED);
1305         assert(container->state & CLASS_LINKED);
1306
1307         /* now we must find the declaration of the field in `container`
1308          * or one of its superclasses */
1309
1310 #ifdef RESOLVE_VERBOSE
1311                 fprintf(stderr,"    resolving field in class...\n");
1312 #endif
1313
1314         fi = class_resolvefield(container,
1315                                                         ref->fieldref->name,ref->fieldref->descriptor,
1316                                                         referer,true);
1317         if (!fi) {
1318                 if (mode == resolveLazy) {
1319                         /* The field does not exist. But since we were called lazily, */
1320                         /* this error must not be reported now. (It will be reported   */
1321                         /* if eager resolving of this field is ever tried.)           */
1322
1323                         *exceptionptr = NULL;
1324                         return true; /* be lazy */
1325                 }
1326
1327                 return false; /* exception */
1328         }
1329
1330         /* cache the result of the resolution */
1331         ref->fieldref->p.field = fi;
1332
1333 resolved_the_field:
1334
1335 #ifdef ENABLE_VERIFIER
1336         if (opt_verify) {
1337                 checkresult = resolve_field_verifier_checks(ref->referermethod,
1338                                 ref->fieldref,
1339                                 container,
1340                                 fi,
1341                                 /* XXX pass NULL instruction * */
1342                                 (ref->flags & RESOLVE_STATIC) ? ICMD_GETSTATIC : ICMD_GETFIELD,
1343                                 NULL);
1344
1345                 if (checkresult != resolveSucceeded)
1346                         return (bool) checkresult;
1347
1348                 declarer = fi->class;
1349                 assert(declarer);
1350                 assert(declarer->state & CLASS_LOADED);
1351                 assert(declarer->state & CLASS_LINKED);
1352
1353                 /* for non-static accesses we have to check the constraints on the */
1354                 /* instance type */
1355
1356                 if (!(ref->flags & RESOLVE_STATIC)) {
1357                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
1358                                         &(ref->instancetypes),
1359                                         CLASSREF_OR_CLASSINFO(container),
1360                                         mode, resolveLinkageError);
1361                         if (checkresult != resolveSucceeded)
1362                                 return (bool) checkresult;
1363                 }
1364
1365                 fieldtyperef = ref->fieldref->parseddesc.fd->classref;
1366
1367                 /* for PUT* instructions we have to check the constraints on the value type */
1368                 if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
1369                         assert(fieldtyperef);
1370                         if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
1371                                 /* check subtype constraints */
1372                                 checkresult = resolve_and_check_subtype_set(ref->referermethod,
1373                                                 &(ref->valueconstraints),
1374                                                 CLASSREF_OR_CLASSINFO(fieldtyperef),
1375                                                 mode, resolveLinkageError);
1376                                 if (checkresult != resolveSucceeded)
1377                                         return (bool) checkresult;
1378                         }
1379                 }
1380
1381                 /* check protected access */
1382                 if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
1383                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
1384                                         &(ref->instancetypes),
1385                                         CLASSREF_OR_CLASSINFO(referer),
1386                                         mode,
1387                                         resolveIllegalAccessError);
1388                         if (checkresult != resolveSucceeded)
1389                                 return (bool) checkresult;
1390                 }
1391
1392         }
1393 #endif /* ENABLE_VERIFIER */
1394
1395         /* succeed */
1396         *result = fi;
1397
1398         return true;
1399 }
1400
1401 /* resolve_field_eager *********************************************************
1402  
1403    Resolve an unresolved field reference eagerly.
1404   
1405    IN:
1406        ref..............struct containing the reference
1407    
1408    RETURN VALUE:
1409        fieldinfo * to the field, or
1410            NULL if an exception has been thrown
1411    
1412 *******************************************************************************/
1413
1414 fieldinfo * resolve_field_eager(unresolved_field *ref)
1415 {
1416         fieldinfo *fi;
1417
1418         if (!resolve_field(ref,resolveEager,&fi))
1419                 return NULL;
1420
1421         return fi;
1422 }
1423
1424 /******************************************************************************/
1425 /* METHOD RESOLUTION                                                          */
1426 /******************************************************************************/
1427
1428 /* resolve_method_invokespecial_lookup *****************************************
1429  
1430    Do the special lookup for methods invoked by INVOKESPECIAL
1431   
1432    IN:
1433        refmethod........the method containing the reference
1434            mi...............the methodinfo of the resolved method
1435   
1436    RETURN VALUE:
1437        a methodinfo *...the result of the lookup,
1438            NULL.............an exception has been thrown
1439    
1440 *******************************************************************************/
1441
1442 methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
1443                                                                                                  methodinfo *mi)
1444 {
1445         classinfo *declarer;
1446         classinfo *referer;
1447
1448         assert(refmethod);
1449         assert(mi);
1450
1451         /* get referer and declarer classes */
1452
1453         referer = refmethod->class;
1454         assert(referer);
1455
1456         declarer = mi->class;
1457         assert(declarer);
1458         assert(referer->state & CLASS_LINKED);
1459
1460         /* checks for INVOKESPECIAL:                                       */
1461         /* for <init> and methods of the current class we don't need any   */
1462         /* special checks. Otherwise we must verify that the called method */
1463         /* belongs to a super class of the current class                   */
1464
1465         if ((referer != declarer) && (mi->name != utf_init)) {
1466                 /* check that declarer is a super class of the current class   */
1467
1468                 if (!class_issubclass(referer,declarer)) {
1469                         *exceptionptr = new_verifyerror(refmethod,
1470                                         "INVOKESPECIAL calling non-super class method");
1471                         return NULL;
1472                 }
1473
1474                 /* if the referer has ACC_SUPER set, we must do the special    */
1475                 /* lookup starting with the direct super class of referer      */
1476
1477                 if ((referer->flags & ACC_SUPER) != 0) {
1478                         mi = class_resolvemethod(referer->super.cls,
1479                                                                          mi->name,
1480                                                                          mi->descriptor);
1481                         if (!mi) {
1482                                 /* the spec calls for an AbstractMethodError in this case */
1483                                 *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
1484                                 return NULL;
1485                         }
1486                 }
1487         }
1488
1489         /* everything ok */
1490         return mi;
1491 }
1492
1493 /* resolve_method_verifier_checks **********************************************
1494  
1495    Do the verifier checks necessary after a method has been resolved.
1496   
1497    IN:
1498        refmethod........the method containing the reference
1499            methodref........the method reference
1500            container........the class where the method was found
1501            mi...............the methodinfo of the resolved method
1502            invokestatic.....true if the method is invoked by INVOKESTATIC
1503   
1504    RETURN VALUE:
1505        resolveSucceeded....everything ok
1506            resolveDeferred.....tests could not be done, have been deferred
1507        resolveFailed.......exception has been thrown
1508    
1509 *******************************************************************************/
1510
1511 #if defined(ENABLE_VERIFIER)
1512 resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
1513                                                                                                 constant_FMIref *methodref,
1514                                                                                                 classinfo *container,
1515                                                                                                 methodinfo *mi,
1516                                                                                                 bool invokestatic,
1517                                                                                                 bool invokespecial,
1518                                                                                                 stackptr curstack)
1519 {
1520         classinfo *declarer;
1521         classinfo *referer;
1522         resolve_result_t result;
1523         int instancecount;
1524         typedesc *paramtypes;
1525         int i;
1526         stackelement *instanceslot = NULL;
1527         stackelement *param;
1528         methoddesc *md;
1529         typeinfo tinfo;
1530         int type;
1531
1532         assert(refmethod);
1533         assert(methodref);
1534         assert(container);
1535         assert(mi);
1536
1537 #ifdef RESOLVE_VERBOSE
1538         fprintf(stderr,"resolve_method_verifier_checks\n");
1539         fprintf(stderr,"    flags: %02x\n",mi->flags);
1540 #endif
1541
1542         /* get the classinfos and the method descriptor */
1543
1544         referer = refmethod->class;
1545         assert(referer);
1546
1547         declarer = mi->class;
1548         assert(declarer);
1549         assert(referer->state & CLASS_LINKED);
1550
1551         md = methodref->parseddesc.md;
1552         assert(md);
1553         assert(md->params);
1554
1555         instancecount = (invokestatic) ? 0 : 1;
1556
1557         /* check static */
1558
1559         if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
1560                 /* a static method is accessed via an instance, or vice versa */
1561                 *exceptionptr =
1562                         new_exception_message(string_java_lang_IncompatibleClassChangeError,
1563                                 (mi->flags & ACC_STATIC) ? "static method called via instance"
1564                                                          : "instance method called without instance");
1565                 return resolveFailed;
1566         }
1567
1568         /* check access rights */
1569
1570         if (!access_is_accessible_member(referer,declarer,mi->flags)) {
1571                 int msglen;
1572                 char *message;
1573
1574                 /* XXX clean this up. this should be in exceptions.c */
1575                 msglen = utf_strlen(declarer->name) + utf_strlen(mi->name) +
1576                         utf_strlen(mi->descriptor) + utf_strlen(referer->name) + 100;
1577                 message = MNEW(char,msglen);
1578                 strcpy(message,"method is not accessible (");
1579                 utf_sprint_classname(message+strlen(message),declarer->name);
1580                 strcat(message,".");
1581                 utf_sprint(message+strlen(message),mi->name);
1582                 utf_sprint(message+strlen(message),mi->descriptor);
1583                 strcat(message," from ");
1584                 utf_sprint_classname(message+strlen(message),referer->name);
1585                 strcat(message,")");
1586                 *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
1587                 MFREE(message,char,msglen);
1588                 return resolveFailed; /* exception */
1589         }
1590
1591         if (curstack) {
1592                 /* for non-static methods we have to check the constraints on the         */
1593                 /* instance type                                                          */
1594
1595                 if (!invokestatic) {
1596                         /* find the instance slot under all the parameter slots on the stack */
1597                         instanceslot = curstack;
1598                         for (i=1; i<md->paramcount; ++i)
1599                                 instanceslot = instanceslot->prev;
1600                 }
1601
1602                 assert((instanceslot && instancecount == 1) || invokestatic);
1603
1604                 /* record subtype constraints for the instance type, if any */
1605                 if (instanceslot) {
1606                         typeinfo *tip;
1607
1608                         assert(instanceslot->type == TYPE_ADR);
1609
1610                         if (invokespecial &&
1611                                         TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
1612                         {   /* XXX clean up */
1613                                 instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
1614                                 classref_or_classinfo initclass = (ins) ? CLASSREF_OR_CLASSINFO(ins[-1].target)
1615                                                                                          : CLASSREF_OR_CLASSINFO(refmethod->class);
1616                                 tip = &tinfo;
1617                                 if (!typeinfo_init_class(tip,initclass))
1618                                         return false;
1619                         }
1620                         else {
1621                                 tip = &(instanceslot->typeinfo);
1622                         }
1623
1624                         result = resolve_lazy_subtype_checks(refmethod,
1625                                                                                                  tip,
1626                                                                                                  CLASSREF_OR_CLASSINFO(container),
1627                                                                                                  resolveLinkageError);
1628                         if (result != resolveSucceeded)
1629                                 return result;
1630
1631                         /* check protected access */
1632
1633                         if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
1634                         {
1635                                 result = resolve_lazy_subtype_checks(refmethod,
1636                                                 tip,
1637                                                 CLASSREF_OR_CLASSINFO(referer),
1638                                                 resolveIllegalAccessError);
1639                                 if (result != resolveSucceeded)
1640                                         return result;
1641                         }
1642
1643                 }
1644
1645                 /* check subtype constraints for TYPE_ADR parameters */
1646
1647                 assert(md->paramcount == methodref->parseddesc.md->paramcount);
1648                 paramtypes = md->paramtypes;
1649                 param = curstack;
1650
1651                 for (i = md->paramcount-1-instancecount; i>=0; --i, param = param->prev) {
1652                         type = md->paramtypes[i+instancecount].type;
1653
1654                         assert(param);
1655                         assert(type == param->type);
1656
1657                         if (type == TYPE_ADR) {
1658                                 result = resolve_lazy_subtype_checks(refmethod,
1659                                                 &(param->typeinfo),
1660                                                 CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
1661                                                 resolveLinkageError);
1662                                 if (result != resolveSucceeded)
1663                                         return result;
1664                         }
1665                 }
1666
1667         } /* if (curstack) */
1668
1669         /* impose loading constraints on parameters (including instance) */
1670
1671         paramtypes = md->paramtypes;
1672
1673         for (i = 0; i < md->paramcount; i++) {
1674                 if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
1675                         utf *name;
1676
1677                         if (i < instancecount) {
1678                                 /* The type of the 'this' pointer is the class containing */
1679                                 /* the method definition. Since container is the same as, */
1680                                 /* or a subclass of declarer, we also constrain declarer  */
1681                                 /* by transitivity of loading constraints.                */
1682                                 name = container->name;
1683                         }
1684                         else {
1685                                 name = paramtypes[i].classref->name;
1686                         }
1687
1688                         /* The caller (referer) and the callee (container) must agree */
1689                         /* on the types of the parameters.                            */
1690                         if (!classcache_add_constraint(referer->classloader,
1691                                                                                    container->classloader, name))
1692                                 return resolveFailed; /* exception */
1693                 }
1694         }
1695
1696         /* impose loading constraint onto return type */
1697
1698         if (md->returntype.type == TYPE_ADR) {
1699                 /* The caller (referer) and the callee (container) must agree */
1700                 /* on the return type.                                        */
1701                 if (!classcache_add_constraint(referer->classloader,container->classloader,
1702                                 md->returntype.classref->name))
1703                         return resolveFailed; /* exception */
1704         }
1705
1706         /* everything ok */
1707         return resolveSucceeded;
1708 }
1709 #endif /* defined(ENABLE_VERIFIER) */
1710
1711 /* resolve_method_lazy *********************************************************
1712  
1713    Resolve an unresolved method reference lazily
1714   
1715    IN:
1716        iptr.............instruction containing the method reference
1717            curstack.........instack of the instruction
1718            refmethod........the referer method
1719   
1720    RETURN VALUE:
1721        resolveSucceeded.....the reference has been resolved
1722        resolveDeferred......the resolving could not be performed lazily
1723            resolveFailed........resolving failed, an exception has been thrown.
1724    
1725 *******************************************************************************/
1726
1727 resolve_result_t resolve_method_lazy(instruction *iptr,stackptr curstack,
1728                                                                          methodinfo *refmethod)
1729 {
1730         classinfo *referer;
1731         classinfo *container;
1732         methodinfo *mi;
1733         constant_FMIref *methodref;
1734         resolve_result_t result;
1735
1736         assert(iptr);
1737         assert(refmethod);
1738
1739 #ifdef RESOLVE_VERBOSE
1740         fprintf(stderr,"resolve_method_lazy\n");
1741 #endif
1742
1743         /* the class containing the reference */
1744
1745         referer = refmethod->class;
1746         assert(referer);
1747
1748         /* the method reference */
1749
1750         INSTRUCTION_GET_METHODREF(iptr,methodref);
1751
1752         /* check if the method itself is already resolved */
1753
1754         if (IS_FMIREF_RESOLVED(methodref)) {
1755                 mi = methodref->p.method;
1756                 container = mi->class;
1757                 goto resolved_the_method;
1758         }
1759
1760         /* first we must resolve the class containg the method */
1761
1762         if (!resolve_class_from_name(referer,refmethod,
1763                                            methodref->p.classref->name,resolveLazy,true,true,&container))
1764         {
1765                 /* the class reference could not be resolved */
1766                 return resolveFailed; /* exception */
1767         }
1768         if (!container)
1769                 return resolveDeferred; /* be lazy */
1770
1771         assert(container->state & CLASS_LINKED);
1772
1773         /* now we must find the declaration of the method in `container`
1774          * or one of its superclasses */
1775
1776         if (container->flags & ACC_INTERFACE) {
1777                 mi = class_resolveinterfacemethod(container,
1778                                                                               methodref->name,
1779                                                                                   methodref->descriptor,
1780                                                                               referer, true);
1781
1782         } else {
1783                 mi = class_resolveclassmethod(container,
1784                                                                           methodref->name,
1785                                                                           methodref->descriptor,
1786                                                                           referer, true);
1787         }
1788
1789         if (!mi) {
1790                 /* The method does not exist. But since we were called lazily, */
1791                 /* this error must not be reported now. (It will be reported   */
1792                 /* if eager resolving of this method is ever tried.)           */
1793
1794                 *exceptionptr = NULL;
1795                 return resolveDeferred; /* be lazy */
1796         }
1797
1798         if (iptr->opc == ICMD_INVOKESPECIAL) {
1799                 mi = resolve_method_invokespecial_lookup(refmethod,mi);
1800                 if (!mi)
1801                         return resolveFailed; /* exception */
1802         }
1803
1804         /* have the method params already been parsed? no, do it. */
1805
1806         if (!mi->parseddesc->params)
1807                 if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
1808                         return resolveFailed;
1809
1810         /* cache the result of the resolution */
1811
1812         methodref->p.method = mi;
1813
1814 resolved_the_method:
1815
1816 #if defined(ENABLE_VERIFIER)
1817         if (opt_verify) {
1818                 result = resolve_method_verifier_checks(refmethod,methodref,container,
1819                                                                                                 mi,
1820                                                                                                 iptr->opc == ICMD_INVOKESTATIC,
1821                                                                                                 iptr->opc == ICMD_INVOKESPECIAL,
1822                                                                                                 curstack);
1823                 if (result != resolveSucceeded)
1824                         return result;
1825         }
1826 #endif /* defined(ENABLE_VERIFIER) */
1827
1828         /* if this call is monomorphic, turn it into an INVOKESPECIAL */
1829
1830         if ((iptr->opc == ICMD_INVOKEVIRTUAL)
1831                 && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
1832         {
1833                 iptr->opc = ICMD_INVOKESPECIAL;
1834         }
1835
1836         /* succeed */
1837         return resolveSucceeded;
1838 }
1839
1840 /* resolve_method **************************************************************
1841  
1842    Resolve an unresolved method reference
1843   
1844    IN:
1845        ref..............struct containing the reference
1846        mode.............mode of resolution:
1847                             resolveLazy...only resolve if it does not
1848                                           require loading classes
1849                             resolveEager..load classes if necessary
1850   
1851    OUT:
1852        *result..........set to the result of resolution, or to NULL if
1853                         the reference has not been resolved
1854                         In the case of an exception, *result is
1855                         guaranteed to be set to NULL.
1856   
1857    RETURN VALUE:
1858        true.............everything ok 
1859                         (*result may still be NULL for resolveLazy)
1860        false............an exception has been thrown
1861    
1862 *******************************************************************************/
1863
1864 bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
1865 {
1866         classinfo *referer;
1867         classinfo *container;
1868         classinfo *declarer;
1869         methodinfo *mi;
1870         typedesc *paramtypes;
1871         int instancecount;
1872         int i;
1873         resolve_result_t checkresult;
1874
1875         assert(ref);
1876         assert(result);
1877         assert(mode == resolveLazy || mode == resolveEager);
1878
1879 #ifdef RESOLVE_VERBOSE
1880         unresolved_method_debug_dump(ref,stderr);
1881 #endif
1882
1883         *result = NULL;
1884
1885         /* the class containing the reference */
1886
1887         referer = ref->referermethod->class;
1888         assert(referer);
1889
1890         /* check if the method itself is already resolved */
1891
1892         if (IS_FMIREF_RESOLVED(ref->methodref)) {
1893                 mi = ref->methodref->p.method;
1894                 container = mi->class;
1895                 goto resolved_the_method;
1896         }
1897
1898         /* first we must resolve the class containing the method */
1899
1900         if (!resolve_class_from_name(referer,ref->referermethod,
1901                                            ref->methodref->p.classref->name,mode,true,true,&container))
1902         {
1903                 /* the class reference could not be resolved */
1904                 return false; /* exception */
1905         }
1906         if (!container)
1907                 return true; /* be lazy */
1908
1909         assert(container);
1910         assert(container->state & CLASS_LINKED);
1911
1912         /* now we must find the declaration of the method in `container`
1913          * or one of its superclasses */
1914
1915         if (container->flags & ACC_INTERFACE) {
1916                 mi = class_resolveinterfacemethod(container,
1917                                                                               ref->methodref->name,
1918                                                                                   ref->methodref->descriptor,
1919                                                                               referer, true);
1920
1921         } else {
1922                 mi = class_resolveclassmethod(container,
1923                                                                           ref->methodref->name,
1924                                                                           ref->methodref->descriptor,
1925                                                                           referer, true);
1926         }
1927
1928         if (!mi) {
1929                 if (mode == resolveLazy) {
1930                         /* The method does not exist. But since we were called lazily, */
1931                         /* this error must not be reported now. (It will be reported   */
1932                         /* if eager resolving of this method is ever tried.)           */
1933
1934                         *exceptionptr = NULL;
1935                         return true; /* be lazy */
1936                 }
1937
1938                 return false; /* exception */ /* XXX set exceptionptr? */
1939         }
1940
1941         /* { the method reference has been resolved } */
1942
1943         if (ref->flags & RESOLVE_SPECIAL) {
1944                 mi = resolve_method_invokespecial_lookup(ref->referermethod,mi);
1945                 if (!mi)
1946                         return false; /* exception */
1947         }
1948
1949         /* have the method params already been parsed? no, do it. */
1950
1951         if (!mi->parseddesc->params)
1952                 if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
1953                         return false;
1954
1955         /* cache the resolution */
1956
1957         ref->methodref->p.method = mi;
1958
1959 resolved_the_method:
1960
1961 #ifdef ENABLE_VERIFIER
1962         if (opt_verify) {
1963
1964                 checkresult = resolve_method_verifier_checks(ref->referermethod,
1965                                 ref->methodref,
1966                                 container,
1967                                 mi,
1968                                 (ref->flags & RESOLVE_STATIC),
1969                                 (ref->flags & RESOLVE_SPECIAL),
1970                                 NULL);
1971
1972                 if (checkresult != resolveSucceeded)
1973                         return (bool) checkresult;
1974
1975                 declarer = mi->class;
1976                 assert(declarer);
1977                 assert(referer->state & CLASS_LINKED);
1978
1979                 /* for non-static methods we have to check the constraints on the         */
1980                 /* instance type                                                          */
1981
1982                 if (!(ref->flags & RESOLVE_STATIC)) {
1983                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
1984                                         &(ref->instancetypes),
1985                                         CLASSREF_OR_CLASSINFO(container),
1986                                         mode,
1987                                         resolveLinkageError);
1988                         if (checkresult != resolveSucceeded)
1989                                 return (bool) checkresult;
1990                         instancecount = 1;
1991                 }
1992                 else {
1993                         instancecount = 0;
1994                 }
1995
1996                 /* check subtype constraints for TYPE_ADR parameters */
1997
1998                 assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
1999                 paramtypes = mi->parseddesc->paramtypes;
2000
2001                 for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
2002                         if (paramtypes[i+instancecount].type == TYPE_ADR) {
2003                                 if (ref->paramconstraints) {
2004                                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
2005                                                         ref->paramconstraints + i,
2006                                                         CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
2007                                                         mode,
2008                                                         resolveLinkageError);
2009                                         if (checkresult != resolveSucceeded)
2010                                                 return (bool) checkresult;
2011                                 }
2012                         }
2013                 }
2014
2015                 /* check protected access */
2016
2017                 if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
2018                 {
2019                         checkresult = resolve_and_check_subtype_set(ref->referermethod,
2020                                         &(ref->instancetypes),
2021                                         CLASSREF_OR_CLASSINFO(referer),
2022                                         mode,
2023                                         resolveIllegalAccessError);
2024                         if (checkresult != resolveSucceeded)
2025                                 return (bool) checkresult;
2026                 }
2027         }
2028 #endif /* ENABLE_VERIFIER */
2029
2030         /* succeed */
2031         *result = mi;
2032         return true;
2033 }
2034
2035 /* resolve_method_eager ********************************************************
2036  
2037    Resolve an unresolved method reference eagerly.
2038   
2039    IN:
2040        ref..............struct containing the reference
2041    
2042    RETURN VALUE:
2043        methodinfo * to the method, or
2044            NULL if an exception has been thrown
2045    
2046 *******************************************************************************/
2047
2048 methodinfo * resolve_method_eager(unresolved_method *ref)
2049 {
2050         methodinfo *mi;
2051
2052         if (!resolve_method(ref,resolveEager,&mi))
2053                 return NULL;
2054
2055         return mi;
2056 }
2057
2058 /******************************************************************************/
2059 /* CREATING THE DATA STRUCTURES                                               */
2060 /******************************************************************************/
2061
2062 #ifdef ENABLE_VERIFIER
2063 static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
2064                                                                                                  methodinfo *refmethod,
2065                                                                                                  unresolved_subtype_set *stset,
2066                                                                                                  typeinfo *tinfo,
2067                                                                                                  constant_classref *declaredtype)
2068 {
2069         int count;
2070         int i;
2071
2072         assert(stset);
2073         assert(tinfo);
2074
2075 #ifdef RESOLVE_VERBOSE
2076         fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
2077 #ifdef TYPEINFO_DEBUG
2078         typeinfo_print(stderr,tinfo,4);
2079 #endif
2080         fprintf(stderr,"    declared type:");utf_fprint(stderr,declaredtype->name);
2081         fprintf(stderr,"\n");
2082 #endif
2083
2084         if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
2085                 *exceptionptr = new_verifyerror(refmethod,
2086                                 "Invalid use of returnAddress");
2087                 return false;
2088         }
2089
2090         if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
2091                 *exceptionptr = new_verifyerror(refmethod,
2092                                 "Invalid use of uninitialized object");
2093                 return false;
2094         }
2095
2096         /* the nulltype is always assignable */
2097         if (TYPEINFO_IS_NULLTYPE(*tinfo))
2098                 goto empty_set;
2099
2100         /* every type is assignable to (BOOTSTRAP)java.lang.Object */
2101         if (declaredtype->name == utf_java_lang_Object
2102                         && referer->classloader == NULL)
2103         {
2104                 goto empty_set;
2105         }
2106
2107         if (tinfo->merged) {
2108                 count = tinfo->merged->count;
2109                 stset->subtyperefs = MNEW(classref_or_classinfo,count + 1);
2110                 for (i=0; i<count; ++i) {
2111                         classref_or_classinfo c = tinfo->merged->list[i];
2112                         if (tinfo->dimension > 0) {
2113                                 /* a merge of array types */
2114                                 /* the merged list contains the possible _element_ types, */
2115                                 /* so we have to create array types with these elements.  */
2116                                 if (IS_CLASSREF(c)) {
2117                                         c.ref = class_get_classref_multiarray_of(tinfo->dimension,c.ref);
2118                                 }
2119                                 else {
2120                                         c.cls = class_multiarray_of(tinfo->dimension,c.cls,false);
2121                                 }
2122                         }
2123                         stset->subtyperefs[i] = c;
2124                 }
2125                 stset->subtyperefs[count].any = NULL; /* terminate */
2126         }
2127         else {
2128                 if ((IS_CLASSREF(tinfo->typeclass)
2129                                         ? tinfo->typeclass.ref->name
2130                                         : tinfo->typeclass.cls->name) == declaredtype->name)
2131                 {
2132                         /* the class names are the same */
2133                     /* equality is guaranteed by the loading constraints */
2134                         goto empty_set;
2135                 }
2136                 else {
2137                         stset->subtyperefs = MNEW(classref_or_classinfo,1 + 1);
2138                         stset->subtyperefs[0] = tinfo->typeclass;
2139                         stset->subtyperefs[1].any = NULL; /* terminate */
2140                 }
2141         }
2142
2143         return true;
2144
2145 empty_set:
2146         UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
2147         return true;
2148 }
2149 #endif /* ENABLE_VERIFIER */
2150
2151 /* create_unresolved_class *****************************************************
2152  
2153    Create an unresolved_class struct for the given class reference
2154   
2155    IN:
2156            refmethod........the method triggering the resolution (if any)
2157            classref.........the class reference
2158            valuetype........value type to check against the resolved class
2159                                                 may be NULL, if no typeinfo is available
2160
2161    RETURN VALUE:
2162        a pointer to a new unresolved_class struct, or
2163            NULL if an exception has been thrown
2164
2165 *******************************************************************************/
2166
2167 #ifdef ENABLE_VERIFIER
2168 unresolved_class * create_unresolved_class(methodinfo *refmethod,
2169                                                                                    constant_classref *classref,
2170                                                                                    typeinfo *valuetype)
2171 {
2172         unresolved_class *ref;
2173
2174 #ifdef RESOLVE_VERBOSE
2175         fprintf(stderr,"create_unresolved_class\n");
2176         fprintf(stderr,"    referer: ");utf_fprint(stderr,classref->referer->name);fputc('\n',stderr);
2177         if (refmethod) {
2178                 fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
2179                 fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
2180         }
2181         fprintf(stderr,"    name   : ");utf_fprint(stderr,classref->name);fputc('\n',stderr);
2182 #endif
2183
2184         ref = NEW(unresolved_class);
2185         ref->classref = classref;
2186         ref->referermethod = refmethod;
2187
2188         if (valuetype) {
2189                 if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
2190                                         &(ref->subtypeconstraints),valuetype,classref))
2191                         return NULL;
2192         }
2193         else {
2194                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
2195         }
2196
2197         return ref;
2198 }
2199 #endif /* ENABLE_VERIFIER */
2200
2201 /* create_unresolved_field *****************************************************
2202  
2203    Create an unresolved_field struct for the given field access instruction
2204   
2205    IN:
2206        referer..........the class containing the reference
2207            refmethod........the method triggering the resolution (if any)
2208            iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
2209
2210    RETURN VALUE:
2211        a pointer to a new unresolved_field struct, or
2212            NULL if an exception has been thrown
2213
2214 *******************************************************************************/
2215
2216 unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refmethod,
2217                                                                                    instruction *iptr)
2218 {
2219         unresolved_field *ref;
2220         constant_FMIref *fieldref = NULL;
2221
2222 #ifdef RESOLVE_VERBOSE
2223         fprintf(stderr,"create_unresolved_field\n");
2224         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
2225         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
2226         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
2227 #endif
2228
2229         ref = NEW(unresolved_field);
2230         ref->flags = 0;
2231         ref->referermethod = refmethod;
2232         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
2233
2234         switch (iptr[0].opc) {
2235                 case ICMD_PUTFIELD:
2236                         ref->flags |= RESOLVE_PUTFIELD;
2237                         fieldref = (constant_FMIref *) iptr[0].val.a;
2238                         break;
2239
2240                 case ICMD_PUTFIELDCONST:
2241                         ref->flags |= RESOLVE_PUTFIELD;
2242                         fieldref = (constant_FMIref *) iptr[1].val.a;
2243                         break;
2244
2245                 case ICMD_PUTSTATIC:
2246                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
2247                         fieldref = (constant_FMIref *) iptr[0].val.a;
2248                         break;
2249
2250                 case ICMD_PUTSTATICCONST:
2251                         ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
2252                         fieldref = (constant_FMIref *) iptr[1].val.a;
2253                         break;
2254
2255                 case ICMD_GETFIELD:
2256                         fieldref = (constant_FMIref *) iptr[0].val.a;
2257                         break;
2258
2259                 case ICMD_GETSTATIC:
2260                         ref->flags |= RESOLVE_STATIC;
2261                         fieldref = (constant_FMIref *) iptr[0].val.a;
2262                         break;
2263         }
2264
2265         assert(fieldref);
2266
2267 #ifdef RESOLVE_VERBOSE
2268         fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
2269         fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
2270         fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
2271         fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
2272         fputc('\n',stderr);
2273         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
2274 #endif
2275
2276         ref->fieldref = fieldref;
2277
2278         return ref;
2279 }
2280
2281 /* constrain_unresolved_field **************************************************
2282  
2283    Record subtype constraints for a field access.
2284   
2285    IN:
2286        ref..............the unresolved_field structure of the access
2287        referer..........the class containing the reference
2288            refmethod........the method triggering the resolution (if any)
2289            iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
2290            stack............the input stack of the instruction
2291
2292    RETURN VALUE:
2293        true.............everything ok
2294            false............an exception has been thrown
2295
2296 *******************************************************************************/
2297
2298 #ifdef ENABLE_VERIFIER
2299 bool constrain_unresolved_field(unresolved_field *ref,
2300                                                             classinfo *referer, methodinfo *refmethod,
2301                                                             instruction *iptr,
2302                                                             stackelement *stack)
2303 {
2304         constant_FMIref *fieldref;
2305         stackelement *instanceslot = NULL;
2306         int type;
2307         typeinfo tinfo;
2308         typeinfo *tip = NULL;
2309         typedesc *fd;
2310
2311         assert(ref);
2312
2313         fieldref = ref->fieldref;
2314         assert(fieldref);
2315
2316 #ifdef RESOLVE_VERBOSE
2317         fprintf(stderr,"constrain_unresolved_field\n");
2318         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
2319         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
2320         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
2321         fprintf(stderr,"    class  : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
2322         fprintf(stderr,"    name   : ");utf_fprint(stderr,fieldref->name);fputc('\n',stderr);
2323         fprintf(stderr,"    desc   : ");utf_fprint(stderr,fieldref->descriptor);fputc('\n',stderr);
2324         fprintf(stderr,"    type   : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
2325         fputc('\n',stderr);
2326         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
2327 #endif
2328
2329         switch (iptr[0].opc) {
2330                 case ICMD_PUTFIELD:
2331                         instanceslot = stack->prev;
2332                         tip = &(stack->typeinfo);
2333                         break;
2334
2335                 case ICMD_PUTFIELDCONST:
2336                         instanceslot = stack;
2337                         break;
2338
2339                 case ICMD_PUTSTATIC:
2340                         tip = &(stack->typeinfo);
2341                         break;
2342
2343                 case ICMD_GETFIELD:
2344                         instanceslot = stack;
2345                         break;
2346         }
2347
2348         assert(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
2349         fd = fieldref->parseddesc.fd;
2350         assert(fd);
2351
2352         /* record subtype constraints for the instance type, if any */
2353         if (instanceslot) {
2354                 typeinfo *insttip;
2355
2356                 /* The instanceslot must contain a reference to a non-array type */
2357                 if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
2358                         *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on non-reference");
2359                         return false;
2360                 }
2361                 if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
2362                         *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
2363                         return false;
2364                 }
2365
2366                 if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
2367                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
2368                 {
2369                         /* The instruction writes a field in an uninitialized object. */
2370                         /* This is only allowed when a field of an uninitialized 'this' object is */
2371                         /* written inside an initialization method                                */
2372
2373                         classinfo *initclass;
2374                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
2375
2376                         if (ins != NULL) {
2377                                 *exceptionptr = new_verifyerror(refmethod,"accessing field of uninitialized object");
2378                                 return false;
2379                         }
2380                         /* XXX check that class of field == refmethod->class */
2381                         initclass = refmethod->class; /* XXX classrefs */
2382                         assert(initclass->state & CLASS_LOADED);
2383                         assert(initclass->state & CLASS_LINKED);
2384
2385                         typeinfo_init_classinfo(&tinfo,initclass);
2386                         insttip = &tinfo;
2387                 }
2388                 else {
2389                         insttip = &(instanceslot->typeinfo);
2390                 }
2391                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
2392                                         &(ref->instancetypes),insttip,fieldref->p.classref))
2393                         return false;
2394         }
2395         else {
2396                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
2397         }
2398
2399         /* record subtype constraints for the value type, if any */
2400         type = fd->type;
2401         if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
2402                 if (!tip) {
2403                         /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
2404                         tip = &tinfo;
2405                         if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
2406                                 assert(class_java_lang_String);
2407                                 assert(class_java_lang_String->state & CLASS_LOADED);
2408                                 assert(class_java_lang_String->state & CLASS_LINKED);
2409                                 typeinfo_init_classinfo(&tinfo,class_java_lang_String);
2410                         }
2411                         else
2412                                 TYPEINFO_INIT_NULLTYPE(tinfo);
2413                 }
2414                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
2415                                         &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
2416                         return false;
2417         }
2418         else {
2419                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
2420         }
2421
2422         return true;
2423 }
2424 #endif /* ENABLE_VERIFIER */
2425
2426 /* create_unresolved_method ****************************************************
2427  
2428    Create an unresolved_method struct for the given method invocation
2429   
2430    IN:
2431        referer..........the class containing the reference
2432            refmethod........the method triggering the resolution (if any)
2433            iptr.............the INVOKE* instruction
2434
2435    RETURN VALUE:
2436        a pointer to a new unresolved_method struct, or
2437            NULL if an exception has been thrown
2438
2439 *******************************************************************************/
2440
2441 unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *refmethod,
2442                                                                                          instruction *iptr)
2443 {
2444         unresolved_method *ref;
2445         constant_FMIref *methodref;
2446         bool staticmethod;
2447
2448         methodref = (constant_FMIref *) iptr[0].val.a;
2449         assert(methodref);
2450         staticmethod = (iptr[0].opc == ICMD_INVOKESTATIC);
2451
2452 #ifdef RESOLVE_VERBOSE
2453         fprintf(stderr,"create_unresolved_method\n");
2454         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
2455         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
2456         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
2457         fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
2458         fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
2459         fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
2460         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
2461 #endif
2462
2463         /* allocate params if necessary */
2464         if (!methodref->parseddesc.md->params)
2465                 if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
2466                                         (staticmethod) ? ACC_STATIC : ACC_NONE))
2467                         return NULL;
2468
2469         /* create the data structure */
2470         ref = NEW(unresolved_method);
2471         ref->flags = ((staticmethod) ? RESOLVE_STATIC : 0)
2472                            | ((iptr[0].opc == ICMD_INVOKESPECIAL) ? RESOLVE_SPECIAL : 0);
2473         ref->referermethod = refmethod;
2474         ref->methodref = methodref;
2475         ref->paramconstraints = NULL;
2476         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
2477
2478         return ref;
2479 }
2480
2481 /* constrain_unresolved_method *************************************************
2482  
2483    Record subtype constraints for the arguments of a method call.
2484   
2485    IN:
2486        ref..............the unresolved_method structure of the call
2487        referer..........the class containing the reference
2488            refmethod........the method triggering the resolution (if any)
2489            iptr.............the INVOKE* instruction
2490            stack............the input stack of the instruction
2491
2492    RETURN VALUE:
2493        true.............everything ok
2494            false............an exception has been thrown
2495
2496 *******************************************************************************/
2497
2498 #ifdef ENABLE_VERIFIER
2499 bool constrain_unresolved_method(unresolved_method *ref,
2500                                                                  classinfo *referer, methodinfo *refmethod,
2501                                                                  instruction *iptr,
2502                                                                  stackelement *stack)
2503 {
2504         constant_FMIref *methodref;
2505         constant_classref *instanceref;
2506         stackelement *instanceslot = NULL;
2507         stackelement *param;
2508         methoddesc *md;
2509         typeinfo tinfo;
2510         int i,j;
2511         int type;
2512         int instancecount;
2513
2514         assert(ref);
2515         methodref = ref->methodref;
2516         assert(methodref);
2517         md = methodref->parseddesc.md;
2518         assert(md);
2519         assert(md->params != NULL);
2520
2521         /* XXX clean this up */
2522         instanceref = IS_FMIREF_RESOLVED(methodref)
2523                 ? class_get_self_classref(methodref->p.method->class)
2524                 : methodref->p.classref;
2525
2526 #ifdef RESOLVE_VERBOSE
2527         fprintf(stderr,"constrain_unresolved_method\n");
2528         fprintf(stderr,"    referer: ");utf_fprint(stderr,referer->name);fputc('\n',stderr);
2529         fprintf(stderr,"    rmethod: ");utf_fprint(stderr,refmethod->name);fputc('\n',stderr);
2530         fprintf(stderr,"    rmdesc : ");utf_fprint(stderr,refmethod->descriptor);fputc('\n',stderr);
2531         fprintf(stderr,"    class  : ");utf_fprint(stderr,methodref->classref->name);fputc('\n',stderr);
2532         fprintf(stderr,"    name   : ");utf_fprint(stderr,methodref->name);fputc('\n',stderr);
2533         fprintf(stderr,"    desc   : ");utf_fprint(stderr,methodref->descriptor);fputc('\n',stderr);
2534         /*fprintf(stderr,"    opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
2535 #endif
2536
2537         if ((ref->flags & RESOLVE_STATIC) == 0) {
2538                 /* find the instance slot under all the parameter slots on the stack */
2539                 instanceslot = stack;
2540                 for (i=1; i<md->paramcount; ++i)
2541                         instanceslot = instanceslot->prev;
2542                 instancecount = 1;
2543         }
2544         else {
2545                 instancecount = 0;
2546         }
2547
2548         assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
2549
2550         /* record subtype constraints for the instance type, if any */
2551         if (instanceslot) {
2552                 typeinfo *tip;
2553
2554                 assert(instanceslot->type == TYPE_ADR);
2555
2556                 if (iptr[0].opc == ICMD_INVOKESPECIAL &&
2557                                 TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
2558                 {   /* XXX clean up */
2559                         instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
2560                         classref_or_classinfo initclass = (ins) ? CLASSREF_OR_CLASSINFO(ins[-1].target)
2561                                                                                  : CLASSREF_OR_CLASSINFO(refmethod->class);
2562                         tip = &tinfo;
2563                         if (!typeinfo_init_class(tip,initclass))
2564                                 return false;
2565                 }
2566                 else {
2567                         tip = &(instanceslot->typeinfo);
2568                 }
2569                 if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
2570                                         &(ref->instancetypes),tip,instanceref))
2571                         return false;
2572         }
2573
2574         /* record subtype constraints for the parameter types, if any */
2575         param = stack;
2576         for (i=md->paramcount-1-instancecount; i>=0; --i, param=param->prev) {
2577                 type = md->paramtypes[i+instancecount].type;
2578
2579                 assert(param);
2580                 assert(type == param->type);
2581
2582                 if (type == TYPE_ADR) {
2583                         if (!ref->paramconstraints) {
2584                                 ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
2585                                 for (j=md->paramcount-1-instancecount; j>i; --j)
2586                                         UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
2587                         }
2588                         assert(ref->paramconstraints);
2589                         if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
2590                                                 ref->paramconstraints + i,&(param->typeinfo),
2591                                                 md->paramtypes[i+instancecount].classref))
2592                                 return false;
2593                 }
2594                 else {
2595                         if (ref->paramconstraints)
2596                                 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
2597                 }
2598         }
2599
2600         return true;
2601 }
2602 #endif /* ENABLE_VERIFIER */
2603
2604 /******************************************************************************/
2605 /* FREEING MEMORY                                                             */
2606 /******************************************************************************/
2607
2608 #ifdef ENABLE_VERIFIER
2609 inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
2610 {
2611         if (list) {
2612                 classref_or_classinfo *p = list;
2613
2614                 /* this is silly. we *only* need to count the elements for MFREE */
2615                 while ((p++)->any)
2616                         ;
2617                 MFREE(list,classref_or_classinfo,(p - list));
2618         }
2619 }
2620 #endif /* ENABLE_VERIFIER */
2621
2622 /* unresolved_class_free *******************************************************
2623  
2624    Free the memory used by an unresolved_class
2625   
2626    IN:
2627        ref..............the unresolved_class
2628
2629 *******************************************************************************/
2630
2631 void unresolved_class_free(unresolved_class *ref)
2632 {
2633         assert(ref);
2634
2635 #ifdef ENABLE_VERIFIER
2636         unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
2637 #endif
2638         FREE(ref,unresolved_class);
2639 }
2640
2641 /* unresolved_field_free *******************************************************
2642  
2643    Free the memory used by an unresolved_field
2644   
2645    IN:
2646        ref..............the unresolved_field
2647
2648 *******************************************************************************/
2649
2650 void unresolved_field_free(unresolved_field *ref)
2651 {
2652         assert(ref);
2653
2654 #ifdef ENABLE_VERIFIER
2655         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
2656         unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
2657 #endif
2658         FREE(ref,unresolved_field);
2659 }
2660
2661 /* unresolved_method_free ******************************************************
2662  
2663    Free the memory used by an unresolved_method
2664   
2665    IN:
2666        ref..............the unresolved_method
2667
2668 *******************************************************************************/
2669
2670 void unresolved_method_free(unresolved_method *ref)
2671 {
2672         assert(ref);
2673
2674 #ifdef ENABLE_VERIFIER
2675         unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
2676         if (ref->paramconstraints) {
2677                 int i;
2678                 int count = ref->methodref->parseddesc.md->paramcount;
2679
2680                 for (i=0; i<count; ++i)
2681                         unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
2682                 MFREE(ref->paramconstraints,unresolved_subtype_set,count);
2683         }
2684 #endif
2685         FREE(ref,unresolved_method);
2686 }
2687
2688 /******************************************************************************/
2689 /* DEBUG DUMPS                                                                */
2690 /******************************************************************************/
2691
2692 #if !defined(NDEBUG)
2693
2694 /* unresolved_subtype_set_debug_dump *******************************************
2695  
2696    Print debug info for unresolved_subtype_set to stream
2697   
2698    IN:
2699        stset............the unresolved_subtype_set
2700            file.............the stream
2701
2702 *******************************************************************************/
2703
2704 void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
2705 {
2706         classref_or_classinfo *p;
2707
2708         if (SUBTYPESET_IS_EMPTY(*stset)) {
2709                 fprintf(file,"        (empty)\n");
2710         }
2711         else {
2712                 p = stset->subtyperefs;
2713                 for (;p->any; ++p) {
2714                         if (IS_CLASSREF(*p)) {
2715                                 fprintf(file,"        ref: ");
2716                                 utf_fprint(file,p->ref->name);
2717                         }
2718                         else {
2719                                 fprintf(file,"        cls: ");
2720                                 utf_fprint(file,p->cls->name);
2721                         }
2722                         fputc('\n',file);
2723                 }
2724         }
2725 }
2726
2727 /* unresolved_class_debug_dump *************************************************
2728  
2729    Print debug info for unresolved_class to stream
2730   
2731    IN:
2732        ref..............the unresolved_class
2733            file.............the stream
2734
2735 *******************************************************************************/
2736
2737 void unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
2738 {
2739         fprintf(file,"unresolved_class(%p):\n",(void *)ref);
2740         if (ref) {
2741                 fprintf(file,"    referer   : ");
2742                 utf_fprint(file,ref->classref->referer->name); fputc('\n',file);
2743                 fprintf(file,"    refmethod : ");
2744                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
2745                 fprintf(file,"    refmethodd: ");
2746                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
2747                 fprintf(file,"    classname : ");
2748                 utf_fprint(file,ref->classref->name); fputc('\n',file);
2749                 fprintf(file,"    subtypeconstraints:\n");
2750                 unresolved_subtype_set_debug_dump(&(ref->subtypeconstraints),file);
2751         }
2752 }
2753
2754 /* unresolved_field_debug_dump *************************************************
2755  
2756    Print debug info for unresolved_field to stream
2757   
2758    IN:
2759        ref..............the unresolved_field
2760            file.............the stream
2761
2762 *******************************************************************************/
2763
2764 void unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
2765 {
2766         fprintf(file,"unresolved_field(%p):\n",(void *)ref);
2767         if (ref) {
2768                 fprintf(file,"    referer   : ");
2769                 utf_fprint(file,ref->referermethod->class->name); fputc('\n',file);
2770                 fprintf(file,"    refmethod : ");
2771                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
2772                 fprintf(file,"    refmethodd: ");
2773                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
2774                 fprintf(file,"    classname : ");
2775                 utf_fprint(file,FIELDREF_CLASSNAME(ref->fieldref)); fputc('\n',file);
2776                 fprintf(file,"    name      : ");
2777                 utf_fprint(file,ref->fieldref->name); fputc('\n',file);
2778                 fprintf(file,"    descriptor: ");
2779                 utf_fprint(file,ref->fieldref->descriptor); fputc('\n',file);
2780                 fprintf(file,"    parseddesc: ");
2781                 descriptor_debug_print_typedesc(file,ref->fieldref->parseddesc.fd); fputc('\n',file);
2782                 fprintf(file,"    flags     : %04x\n",ref->flags);
2783                 fprintf(file,"    instancetypes:\n");
2784                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
2785                 fprintf(file,"    valueconstraints:\n");
2786                 unresolved_subtype_set_debug_dump(&(ref->valueconstraints),file);
2787         }
2788 }
2789
2790 /* unresolved_method_debug_dump ************************************************
2791  
2792    Print debug info for unresolved_method to stream
2793   
2794    IN:
2795        ref..............the unresolved_method
2796            file.............the stream
2797
2798 *******************************************************************************/
2799
2800 void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
2801 {
2802         int i;
2803
2804         fprintf(file,"unresolved_method(%p):\n",(void *)ref);
2805         if (ref) {
2806                 fprintf(file,"    referer   : ");
2807                 utf_fprint(file,ref->referermethod->class->name); fputc('\n',file);
2808                 fprintf(file,"    refmethod : ");
2809                 utf_fprint(file,ref->referermethod->name); fputc('\n',file);
2810                 fprintf(file,"    refmethodd: ");
2811                 utf_fprint(file,ref->referermethod->descriptor); fputc('\n',file);
2812                 fprintf(file,"    classname : ");
2813                 utf_fprint(file,METHODREF_CLASSNAME(ref->methodref)); fputc('\n',file);
2814                 fprintf(file,"    name      : ");
2815                 utf_fprint(file,ref->methodref->name); fputc('\n',file);
2816                 fprintf(file,"    descriptor: ");
2817                 utf_fprint(file,ref->methodref->descriptor); fputc('\n',file);
2818                 fprintf(file,"    parseddesc: ");
2819                 descriptor_debug_print_methoddesc(file,ref->methodref->parseddesc.md); fputc('\n',file);
2820                 fprintf(file,"    flags     : %04x\n",ref->flags);
2821                 fprintf(file,"    instancetypes:\n");
2822                 unresolved_subtype_set_debug_dump(&(ref->instancetypes),file);
2823                 fprintf(file,"    paramconstraints:\n");
2824                 if (ref->paramconstraints) {
2825                         for (i=0; i<ref->methodref->parseddesc.md->paramcount; ++i) {
2826                                 fprintf(file,"      param %d:\n",i);
2827                                 unresolved_subtype_set_debug_dump(ref->paramconstraints + i,file);
2828                         }
2829                 }
2830                 else {
2831                         fprintf(file,"      (empty)\n");
2832                 }
2833         }
2834 }
2835 #endif /* !defined(NDEBUG) */
2836
2837 /*
2838  * These are local overrides for various environment variables in Emacs.
2839  * Please do not remove this and leave it at the end of the file, where
2840  * Emacs will automagically detect them.
2841  * ---------------------------------------------------------------------
2842  * Local variables:
2843  * mode: c
2844  * indent-tabs-mode: t
2845  * c-basic-offset: 4
2846  * tab-width: 4
2847  * End:
2848  * vim:noexpandtab:sw=4:ts=4:
2849  */
2850