* class_java_lang_NoSuchMethodError: Added.
[cacao.git] / src / vm / class.c
1 /* src/vm/class.c - class related functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    Changes: Mark Probst
30             Andreas Krall
31             Christian Thalinger
32
33    $Id: class.c 3638 2005-11-08 17:21:11Z twisti $
34
35 */
36
37 #include <assert.h>
38 #include <string.h>
39
40 #include "config.h"
41 #include "vm/types.h"
42
43 #include "mm/memory.h"
44
45 #if defined(USE_THREADS)
46 # if defined(NATIVE_THREADS)
47 #  include "threads/native/threads.h"
48 # else
49 #  include "threads/green/threads.h"
50 #  include "threads/green/locks.h"
51 # endif
52 #endif
53
54 #include "toolbox/logging.h"
55 #include "vm/class.h"
56 #include "vm/classcache.h"
57 #include "vm/exceptions.h"
58 #include "vm/global.h"
59 #include "vm/loader.h"
60 #include "vm/options.h"
61 #include "vm/resolve.h"
62 #include "vm/statistics.h"
63 #include "vm/stringlocal.h"
64 #include "vm/tables.h"
65 #include "vm/utf8.h"
66
67
68 /******************************************************************************/
69 /* DEBUG HELPERS                                                              */
70 /******************************************************************************/
71
72 #ifndef NDEBUG
73 #define CLASS_DEBUG
74 #endif
75
76 #ifdef CLASS_DEBUG
77 #define CLASS_ASSERT(cond)  assert(cond)
78 #else
79 #define CLASS_ASSERT(cond)
80 #endif
81
82
83 /* global variables ***********************************************************/
84
85 list unlinkedclasses;                   /* this is only used for eager class  */
86                                         /* loading                            */
87
88
89 /* frequently used classes ****************************************************/
90
91 /* important system classes */
92
93 classinfo *class_java_lang_Object = NULL;
94 classinfo *class_java_lang_Class = NULL;
95 classinfo *class_java_lang_ClassLoader = NULL;
96 classinfo *class_java_lang_Cloneable = NULL;
97 classinfo *class_java_lang_SecurityManager = NULL;
98 classinfo *class_java_lang_String = NULL;
99 classinfo *class_java_lang_System = NULL;
100 classinfo *class_java_lang_Thread = NULL;
101 classinfo *class_java_lang_ThreadGroup = NULL;
102 classinfo *class_java_lang_VMThread = NULL;
103 classinfo *class_java_io_Serializable = NULL;
104
105
106 /* system exception classes required in cacao */
107
108 classinfo *class_java_lang_Throwable = NULL;
109 classinfo *class_java_lang_VMThrowable = NULL;
110 classinfo *class_java_lang_Error = NULL;
111 classinfo *class_java_lang_NoClassDefFoundError = NULL;
112 classinfo *class_java_lang_NoSuchMethodError = NULL;
113 classinfo *class_java_lang_OutOfMemoryError = NULL;
114
115 classinfo *class_java_lang_Exception = NULL;
116 classinfo *class_java_lang_ClassNotFoundException = NULL;
117 classinfo *class_java_lang_IllegalArgumentException = NULL;
118 classinfo *class_java_lang_IllegalMonitorStateException = NULL;
119
120 classinfo *class_java_lang_Void = NULL;
121 classinfo *class_java_lang_Boolean = NULL;
122 classinfo *class_java_lang_Byte = NULL;
123 classinfo *class_java_lang_Character = NULL;
124 classinfo *class_java_lang_Short = NULL;
125 classinfo *class_java_lang_Integer = NULL;
126 classinfo *class_java_lang_Long = NULL;
127 classinfo *class_java_lang_Float = NULL;
128 classinfo *class_java_lang_Double = NULL;
129
130
131 /* some runtime exception */
132
133 classinfo *class_java_lang_NullPointerException = NULL;
134
135
136 /* some classes which may be used more often */
137
138 classinfo *class_java_lang_StackTraceElement = NULL;
139 classinfo *class_java_lang_reflect_Constructor = NULL;
140 classinfo *class_java_lang_reflect_Field = NULL;
141 classinfo *class_java_lang_reflect_Method = NULL;
142 classinfo *class_java_security_PrivilegedAction = NULL;
143 classinfo *class_java_util_Vector = NULL;
144
145 classinfo *arrayclass_java_lang_Object = NULL;
146
147
148 /* pseudo classes for the typechecker */
149
150 classinfo *pseudo_class_Arraystub = NULL;
151 classinfo *pseudo_class_Null = NULL;
152 classinfo *pseudo_class_New = NULL;
153
154
155 /* class_set_packagename *******************************************************
156
157    Derive the package name from the class name and store it in the struct.
158
159 *******************************************************************************/
160
161 void class_set_packagename(classinfo *c)
162 {
163         char *p = UTF_END(c->name) - 1;
164         char *start = c->name->text;
165
166         /* set the package name */
167         /* classes in the unnamed package keep packagename == NULL */
168
169         if (c->name->text[0] == '[') {
170                 /* set packagename of arrays to the element's package */
171
172                 for (; *start == '['; start++);
173
174                 /* skip the 'L' in arrays of references */
175                 if (*start == 'L')
176                         start++;
177
178                 for (; (p > start) && (*p != '/'); --p);
179
180                 c->packagename = utf_new(start, p - start);
181
182         } else {
183                 for (; (p > start) && (*p != '/'); --p);
184
185                 c->packagename = utf_new(start, p - start);
186         }
187 }
188
189
190 /* class_create_classinfo ******************************************************
191
192    Create a new classinfo struct. The class name is set to the given utf *,
193    most other fields are initialized to zero.
194
195    Note: classname may be NULL. In this case a not-yet-named classinfo is
196          created. The name must be filled in later and class_set_packagename
197                  must be called after that.
198
199 *******************************************************************************/
200
201 classinfo *class_create_classinfo(utf *classname)
202 {
203         classinfo *c;
204
205 #if defined(STATISTICS)
206         if (opt_stat)
207                 count_class_infos += sizeof(classinfo);
208 #endif
209
210         /* we use a safe name for temporarily unnamed classes */
211         if (!classname)
212                 classname = utf_not_named_yet;
213
214         if (initverbose)
215                 log_message_utf("Creating class: ", classname);
216
217         /* GCNEW_UNCOLLECTABLE clears the allocated memory */
218
219         c = GCNEW_UNCOLLECTABLE(classinfo, 1);
220         /*c=NEW(classinfo);*/
221         c->name = classname;
222         
223         if (classname != utf_not_named_yet) {
224                 class_set_packagename(c);
225         }
226
227 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
228         initObjectLock(&c->header);
229 #endif
230
231         return c;
232 }
233
234 /* class_freepool **************************************************************
235
236         Frees all resources used by this classes Constant Pool.
237
238 *******************************************************************************/
239
240 static void class_freecpool(classinfo *c)
241 {
242         u4 idx;
243         u4 tag;
244         voidptr info;
245         
246         if (c->cptags && c->cpinfos) {
247                 for (idx = 0; idx < c->cpcount; idx++) {
248                         tag = c->cptags[idx];
249                         info = c->cpinfos[idx];
250                 
251                         if (info != NULL) {
252                                 switch (tag) {
253                                 case CONSTANT_Fieldref:
254                                 case CONSTANT_Methodref:
255                                 case CONSTANT_InterfaceMethodref:
256                                         FREE(info, constant_FMIref);
257                                         break;
258                                 case CONSTANT_Integer:
259                                         FREE(info, constant_integer);
260                                         break;
261                                 case CONSTANT_Float:
262                                         FREE(info, constant_float);
263                                         break;
264                                 case CONSTANT_Long:
265                                         FREE(info, constant_long);
266                                         break;
267                                 case CONSTANT_Double:
268                                         FREE(info, constant_double);
269                                         break;
270                                 case CONSTANT_NameAndType:
271                                         FREE(info, constant_nameandtype);
272                                         break;
273                                 }
274                         }
275                 }
276         }
277
278         if (c->cptags)
279                 MFREE(c->cptags, u1, c->cpcount);
280
281         if (c->cpinfos)
282                 MFREE(c->cpinfos, voidptr, c->cpcount);
283 }
284
285
286 /* class_getconstant ***********************************************************
287
288    Retrieves the value at position 'pos' of the constantpool of a
289    class. If the type of the value is other than 'ctype', an error is
290    thrown.
291
292 *******************************************************************************/
293
294 voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype)
295 {
296         /* check index and type of constantpool entry */
297         /* (pos == 0 is caught by type comparison) */
298
299         if (pos >= c->cpcount || c->cptags[pos] != ctype) {
300                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
301                 return NULL;
302         }
303
304         return c->cpinfos[pos];
305 }
306
307
308 /* innerclass_getconstant ******************************************************
309
310    Like class_getconstant, but if cptags is ZERO, null is returned.
311         
312 *******************************************************************************/
313
314 voidptr innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
315 {
316         /* invalid position in constantpool */
317         if (pos >= c->cpcount) {
318                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
319                 return NULL;
320         }
321
322         /* constantpool entry of type 0 */      
323         if (!c->cptags[pos])
324                 return NULL;
325
326         /* check type of constantpool entry */
327         if (c->cptags[pos] != ctype) {
328                 *exceptionptr = new_classformaterror(c, "Illegal constant pool index");
329                 return NULL;
330         }
331                 
332         return c->cpinfos[pos];
333 }
334
335
336 /* class_free ******************************************************************
337
338    Frees all resources used by the class.
339
340 *******************************************************************************/
341
342 void class_free(classinfo *c)
343 {
344         s4 i;
345         vftbl_t *v;
346                 
347         class_freecpool(c);
348
349         if (c->interfaces)
350                 MFREE(c->interfaces, classinfo*, c->interfacescount);
351
352         if (c->fields) {
353                 for (i = 0; i < c->fieldscount; i++)
354                         field_free(&(c->fields[i]));
355 /*      MFREE(c->fields, fieldinfo, c->fieldscount); */
356         }
357         
358         if (c->methods) {
359                 for (i = 0; i < c->methodscount; i++)
360                         method_free(&(c->methods[i]));
361                 MFREE(c->methods, methodinfo, c->methodscount);
362         }
363
364         if ((v = c->vftbl) != NULL) {
365                 if (v->arraydesc)
366                         mem_free(v->arraydesc,sizeof(arraydescriptor));
367                 
368                 for (i = 0; i < v->interfacetablelength; i++) {
369                         MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
370                 }
371                 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
372
373                 i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
374                     sizeof(methodptr*) * (v->interfacetablelength -
375                                          (v->interfacetablelength > 0));
376                 v = (vftbl_t*) (((methodptr*) v) -
377                                                 (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
378                 mem_free(v, i);
379         }
380
381         if (c->innerclass)
382                 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
383
384         /*      if (c->classvftbl)
385                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
386         
387 /*      GCFREE(c); */
388 }
389
390
391 /* get_array_class *************************************************************
392
393    Returns the array class with the given name for the given
394    classloader, or NULL if an exception occurred.
395
396    Note: This function does eager loading. 
397
398 *******************************************************************************/
399
400 static classinfo *get_array_class(utf *name,java_objectheader *initloader,
401                                                                                         java_objectheader *defloader,bool link)
402 {
403         classinfo *c;
404         
405         /* lookup this class in the classcache */
406         c = classcache_lookup(initloader,name);
407         if (!c)
408                 c = classcache_lookup_defined(defloader,name);
409
410         if (!c) {
411                 /* we have to create it */
412                 c = class_create_classinfo(name);
413                 c = load_newly_created_array(c,initloader);
414                 if (c == NULL)
415                         return NULL;
416         }
417
418         CLASS_ASSERT(c);
419         CLASS_ASSERT(c->loaded);
420         CLASS_ASSERT(c->classloader == defloader);
421
422         if (link && !c->linked)
423                 if (!link_class(c))
424                         return NULL;
425
426         CLASS_ASSERT(!link || c->linked);
427
428         return c;
429 }
430
431
432 /* class_array_of **************************************************************
433
434    Returns an array class with the given component class. The array
435    class is dynamically created if neccessary.
436
437 *******************************************************************************/
438
439 classinfo *class_array_of(classinfo *component, bool link)
440 {
441     s4 namelen;
442     char *namebuf;
443
444     /* Assemble the array class name */
445     namelen = component->name->blength;
446     
447     if (component->name->text[0] == '[') {
448         /* the component is itself an array */
449         namebuf = DMNEW(char, namelen + 1);
450         namebuf[0] = '[';
451         MCOPY(namebuf + 1, component->name->text, char, namelen);
452         namelen++;
453
454     } else {
455         /* the component is a non-array class */
456         namebuf = DMNEW(char, namelen + 3);
457         namebuf[0] = '[';
458         namebuf[1] = 'L';
459         MCOPY(namebuf + 2, component->name->text, char, namelen);
460         namebuf[2 + namelen] = ';';
461         namelen += 3;
462     }
463
464         return get_array_class(utf_new(namebuf, namelen),
465                                                    component->classloader,
466                                                    component->classloader,
467                                                    link);
468 }
469
470
471 /* class_multiarray_of *********************************************************
472
473    Returns an array class with the given dimension and element class.
474    The array class is dynamically created if neccessary.
475
476 *******************************************************************************/
477
478 classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
479 {
480     s4 namelen;
481     char *namebuf;
482
483         if (dim < 1) {
484                 log_text("Invalid array dimension requested");
485                 assert(0);
486         }
487
488     /* Assemble the array class name */
489     namelen = element->name->blength;
490     
491     if (element->name->text[0] == '[') {
492         /* the element is itself an array */
493         namebuf = DMNEW(char, namelen + dim);
494         memcpy(namebuf + dim, element->name->text, namelen);
495         namelen += dim;
496     }
497     else {
498         /* the element is a non-array class */
499         namebuf = DMNEW(char, namelen + 2 + dim);
500         namebuf[dim] = 'L';
501         memcpy(namebuf + dim + 1, element->name->text, namelen);
502         namelen += (2 + dim);
503         namebuf[namelen - 1] = ';';
504     }
505         memset(namebuf, '[', dim);
506
507         return get_array_class(utf_new(namebuf, namelen),
508                                                    element->classloader,
509                                                    element->classloader,
510                                                    link);
511 }
512
513
514 /* class_lookup_classref *******************************************************
515
516    Looks up the constant_classref for a given classname in the classref
517    tables of a class.
518
519    IN:
520        cls..............the class containing the reference
521            name.............the name of the class refered to
522
523     RETURN VALUE:
524            a pointer to a constant_classref, or 
525            NULL if the reference was not found
526    
527 *******************************************************************************/
528
529 constant_classref *class_lookup_classref(classinfo *cls, utf *name)
530 {
531         constant_classref *ref;
532         extra_classref *xref;
533         int count;
534
535         CLASS_ASSERT(cls);
536         CLASS_ASSERT(name);
537         CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
538         
539         /* first search the main classref table */
540         count = cls->classrefcount;
541         ref = cls->classrefs;
542         for (; count; --count, ++ref)
543                 if (ref->name == name)
544                         return ref;
545
546         /* next try the list of extra classrefs */
547         for (xref = cls->extclassrefs; xref; xref = xref->next) {
548                 if (xref->classref.name == name)
549                         return &(xref->classref);
550         }
551
552         /* not found */
553         return NULL;
554 }
555
556
557 /* class_get_classref **********************************************************
558
559    Returns the constant_classref for a given classname.
560
561    IN:
562        cls..............the class containing the reference
563            name.............the name of the class refered to
564
565    RETURN VALUE:
566        a pointer to a constant_classref (never NULL)
567
568    NOTE:
569        The given name is not checked for validity!
570    
571 *******************************************************************************/
572
573 constant_classref *class_get_classref(classinfo *cls, utf *name)
574 {
575         constant_classref *ref;
576         extra_classref *xref;
577
578         CLASS_ASSERT(cls);
579         CLASS_ASSERT(name);
580
581         ref = class_lookup_classref(cls,name);
582         if (ref)
583                 return ref;
584
585         xref = NEW(extra_classref);
586         CLASSREF_INIT(xref->classref,cls,name);
587
588         xref->next = cls->extclassrefs;
589         cls->extclassrefs = xref;
590
591         return &(xref->classref);
592 }
593
594
595 /* class_get_self_classref *****************************************************
596
597    Returns the constant_classref to the class itself.
598
599    IN:
600        cls..............the class containing the reference
601
602    RETURN VALUE:
603        a pointer to a constant_classref (never NULL)
604
605 *******************************************************************************/
606
607 constant_classref *class_get_self_classref(classinfo *cls)
608 {
609         /* XXX this should be done in a faster way. Maybe always make */
610         /* the classref of index 0 a self reference.                  */
611         return class_get_classref(cls,cls->name);
612 }
613
614 /* class_get_classref_multiarray_of ********************************************
615
616    Returns an array type reference with the given dimension and element class
617    reference.
618
619    IN:
620        dim..............the requested dimension
621                             dim must be in [1;255]. This is NOT checked!
622            ref..............the component class reference
623
624    RETURN VALUE:
625        a pointer to the class reference for the array type
626
627    NOTE:
628        The referer of `ref` is used as the referer for the new classref.
629
630 *******************************************************************************/
631
632 constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
633 {
634     s4 namelen;
635     char *namebuf;
636
637         CLASS_ASSERT(ref);
638         CLASS_ASSERT(dim >= 1 && dim <= 255);
639
640     /* Assemble the array class name */
641     namelen = ref->name->blength;
642     
643     if (ref->name->text[0] == '[') {
644         /* the element is itself an array */
645         namebuf = DMNEW(char, namelen + dim);
646         memcpy(namebuf + dim, ref->name->text, namelen);
647         namelen += dim;
648     }
649     else {
650         /* the element is a non-array class */
651         namebuf = DMNEW(char, namelen + 2 + dim);
652         namebuf[dim] = 'L';
653         memcpy(namebuf + dim + 1, ref->name->text, namelen);
654         namelen += (2 + dim);
655         namebuf[namelen - 1] = ';';
656     }
657         memset(namebuf, '[', dim);
658
659     return class_get_classref(ref->referer,utf_new(namebuf, namelen));
660 }
661
662
663 /* class_get_classref_component_of *********************************************
664
665    Returns the component classref of a given array type reference
666
667    IN:
668        ref..............the array type reference
669
670    RETURN VALUE:
671        a reference to the component class, or
672            NULL if `ref` is not an object array type reference
673
674    NOTE:
675        The referer of `ref` is used as the referer for the new classref.
676
677 *******************************************************************************/
678
679 constant_classref *class_get_classref_component_of(constant_classref *ref)
680 {
681         s4 namelen;
682         char *name;
683         
684         CLASS_ASSERT(ref);
685
686         name = ref->name->text;
687         if (*name++ != '[')
688                 return NULL;
689         
690         namelen = ref->name->blength - 1;
691         if (*name == 'L') {
692                 name++;
693                 namelen -= 2;
694         }
695         else if (*name != '[') {
696                 return NULL;
697         }
698
699     return class_get_classref(ref->referer, utf_new(name, namelen));
700 }
701
702
703 /* class_findmethod ************************************************************
704         
705    Searches a 'classinfo' structure for a method having the given name
706    and descriptor. If descriptor is NULL, it is ignored.
707
708 *******************************************************************************/
709
710 methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
711 {
712         methodinfo *m;
713         s4          i;
714
715         for (i = 0; i < c->methodscount; i++) {
716                 m = &(c->methods[i]);
717
718                 if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
719                         return m;
720         }
721
722         return NULL;
723 }
724
725
726 /************************* Function: class_findmethod_approx ******************
727         
728         like class_findmethod but ignores the return value when comparing the
729         descriptor.
730
731 *******************************************************************************/
732
733 methodinfo *class_findmethod_approx(classinfo *c, utf *name, utf *desc)
734 {
735         s4 i;
736
737         for (i = 0; i < c->methodscount; i++) {
738                 if (c->methods[i].name == name) {
739                         utf *meth_descr = c->methods[i].descriptor;
740                         
741                         if (desc == NULL) 
742                                 /* ignore type */
743                                 return &(c->methods[i]);
744
745                         if (desc->blength <= meth_descr->blength) {
746                                 /* current position in utf text   */
747                                 char *desc_utf_ptr = desc->text;      
748                                 char *meth_utf_ptr = meth_descr->text;                                    
749                                 /* points behind utf strings */
750                                 char *desc_end = UTF_END(desc);         
751                                 char *meth_end = UTF_END(meth_descr);   
752                                 char ch;
753
754                                 /* compare argument types */
755                                 while (desc_utf_ptr < desc_end && meth_utf_ptr < meth_end) {
756
757                                         if ((ch = *desc_utf_ptr++) != (*meth_utf_ptr++))
758                                                 break; /* no match */
759
760                                         if (ch == ')')
761                                                 return &(c->methods[i]); /* all parameter types equal */
762                                 }
763                         }
764                 }
765         }
766
767         return NULL;
768 }
769
770
771 /* class_resolvemethod *********************************************************
772         
773    Searches a class and it's super classes for a method.
774
775    Superinterfaces are *not* searched.
776
777 *******************************************************************************/
778
779 methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
780 {
781         methodinfo *m;
782
783         while (c) {
784                 m = class_findmethod(c, name, desc);
785
786                 if (m)
787                         return m;
788
789                 /* JVM Specification bug: 
790
791                    It is important NOT to resolve special <init> and <clinit>
792                    methods to super classes or interfaces; yet, this is not
793                    explicited in the specification.  Section 5.4.3.3 should be
794                    updated appropriately.  */
795
796                 if (name == utf_init || name == utf_clinit)
797                         return NULL;
798
799                 c = c->super.cls;
800         }
801
802         return NULL;
803 }
804
805
806 /* class_resolveinterfacemethod_intern *****************************************
807
808    Internally used helper function. Do not use this directly.
809
810 *******************************************************************************/
811
812 static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
813                                                                                                            utf *name, utf *desc)
814 {
815         methodinfo *m;
816         s4          i;
817         
818         m = class_findmethod(c, name, desc);
819
820         if (m)
821                 return m;
822
823         /* try the superinterfaces */
824
825         for (i = 0; i < c->interfacescount; i++) {
826                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
827                                                                                                 name, desc);
828
829                 if (m)
830                         return m;
831         }
832         
833         return NULL;
834 }
835
836
837 /* class_resolveclassmethod ****************************************************
838         
839    Resolves a reference from REFERER to a method with NAME and DESC in
840    class C.
841
842    If the method cannot be resolved the return value is NULL. If
843    EXCEPT is true *exceptionptr is set, too.
844
845 *******************************************************************************/
846
847 methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
848                                                                          classinfo *referer, bool except)
849 {
850         classinfo  *cls;
851         methodinfo *m;
852         s4          i;
853
854         /* XXX resolve class c */
855         /* XXX check access from REFERER to C */
856         
857 /*      if (c->flags & ACC_INTERFACE) { */
858 /*              if (except) */
859 /*                      *exceptionptr = */
860 /*                              new_exception(string_java_lang_IncompatibleClassChangeError); */
861 /*              return NULL; */
862 /*      } */
863
864         /* try class c and its superclasses */
865
866         cls = c;
867
868         m = class_resolvemethod(cls, name, desc);
869
870         if (m)
871                 goto found;
872
873         /* try the superinterfaces */
874
875         for (i = 0; i < c->interfacescount; i++) {
876                 m = class_resolveinterfacemethod_intern(c->interfaces[i].cls,
877                                                                                                  name, desc);
878
879                 if (m)
880                         goto found;
881         }
882         
883         if (except)
884                 *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
885
886         return NULL;
887
888  found:
889         if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
890                 if (except)
891                         *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
892
893                 return NULL;
894         }
895
896         /* XXX check access rights */
897
898         return m;
899 }
900
901
902 /* class_resolveinterfacemethod ************************************************
903
904    Resolves a reference from REFERER to a method with NAME and DESC in
905    interface C.
906
907    If the method cannot be resolved the return value is NULL. If
908    EXCEPT is true *exceptionptr is set, too.
909
910 *******************************************************************************/
911
912 methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
913                                                                                  classinfo *referer, bool except)
914 {
915         methodinfo *mi;
916
917         /* XXX resolve class c */
918         /* XXX check access from REFERER to C */
919         
920         if (!(c->flags & ACC_INTERFACE)) {
921                 if (except)
922                         *exceptionptr =
923                                 new_exception(string_java_lang_IncompatibleClassChangeError);
924
925                 return NULL;
926         }
927
928         mi = class_resolveinterfacemethod_intern(c, name, desc);
929
930         if (mi)
931                 return mi;
932
933         /* try class java.lang.Object */
934
935         mi = class_findmethod(class_java_lang_Object, name, desc);
936
937         if (mi)
938                 return mi;
939
940         if (except)
941                 *exceptionptr =
942                         exceptions_new_nosuchmethoderror(c, name, desc);
943
944         return NULL;
945 }
946
947
948 /* class_findfield *************************************************************
949         
950    Searches for field with specified name and type in a classinfo
951    structure. If no such field is found NULL is returned.
952
953 *******************************************************************************/
954
955 fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
956 {
957         s4 i;
958
959         for (i = 0; i < c->fieldscount; i++)
960                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
961                         return &(c->fields[i]);
962
963         if (c->super.cls)
964                 return class_findfield(c->super.cls, name, desc);
965
966         return NULL;
967 }
968
969
970 /* class_findfield_approx ******************************************************
971         
972    Searches in 'classinfo'-structure for a field with the specified
973    name.
974
975 *******************************************************************************/
976  
977 fieldinfo *class_findfield_by_name(classinfo *c, utf *name)
978 {
979         s4 i;
980
981         /* get field index */
982
983         i = class_findfield_index_by_name(c, name);
984
985         /* field was not found, return */
986
987         if (i == -1)
988                 return NULL;
989
990         /* return field address */
991
992         return &(c->fields[i]);
993 }
994
995
996 s4 class_findfield_index_by_name(classinfo *c, utf *name)
997 {
998         s4 i;
999
1000         for (i = 0; i < c->fieldscount; i++) {
1001                 /* compare field names */
1002
1003                 if ((c->fields[i].name == name))
1004                         return i;
1005         }
1006
1007         /* field was not found, raise exception */      
1008
1009         *exceptionptr = new_exception(string_java_lang_NoSuchFieldException);
1010
1011         return -1;
1012 }
1013
1014
1015 /****************** Function: class_resolvefield_int ***************************
1016
1017     This is an internally used helper function. Do not use this directly.
1018
1019         Tries to resolve a field having the given name and type.
1020     If the field cannot be resolved, NULL is returned.
1021
1022 *******************************************************************************/
1023
1024 static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
1025 {
1026         fieldinfo *fi;
1027         s4         i;
1028
1029         /* search for field in class c */
1030
1031         for (i = 0; i < c->fieldscount; i++) { 
1032                 if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
1033                         return &(c->fields[i]);
1034                 }
1035     }
1036
1037         /* try superinterfaces recursively */
1038
1039         for (i = 0; i < c->interfacescount; i++) {
1040                 fi = class_resolvefield_int(c->interfaces[i].cls, name, desc);
1041                 if (fi)
1042                         return fi;
1043         }
1044
1045         /* try superclass */
1046
1047         if (c->super.cls)
1048                 return class_resolvefield_int(c->super.cls, name, desc);
1049
1050         /* not found */
1051
1052         return NULL;
1053 }
1054
1055
1056 /********************* Function: class_resolvefield ***************************
1057         
1058         Resolves a reference from REFERER to a field with NAME and DESC in class C.
1059
1060     If the field cannot be resolved the return value is NULL. If EXCEPT is
1061     true *exceptionptr is set, too.
1062
1063 *******************************************************************************/
1064
1065 fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
1066                                                           classinfo *referer, bool except)
1067 {
1068         fieldinfo *fi;
1069
1070         /* XXX resolve class c */
1071         /* XXX check access from REFERER to C */
1072         
1073         fi = class_resolvefield_int(c, name, desc);
1074
1075         if (!fi) {
1076                 if (except)
1077                         *exceptionptr =
1078                                 new_exception_utfmessage(string_java_lang_NoSuchFieldError,
1079                                                                                  name);
1080
1081                 return NULL;
1082         }
1083
1084         /* XXX check access rights */
1085
1086         return fi;
1087 }
1088
1089
1090 /* class_issubclass ************************************************************
1091
1092    Checks if sub is a descendant of super.
1093         
1094 *******************************************************************************/
1095
1096 bool class_issubclass(classinfo *sub, classinfo *super)
1097 {
1098         for (;;) {
1099                 if (!sub)
1100                         return false;
1101
1102                 if (sub == super)
1103                         return true;
1104
1105                 sub = sub->super.cls;
1106         }
1107 }
1108
1109
1110 void class_showconstanti(classinfo *c, int ii) 
1111 {
1112         u4 i = ii;
1113         voidptr e;
1114                 
1115         e = c->cpinfos [i];
1116         printf ("#%d:  ", (int) i);
1117         if (e) {
1118                 switch (c->cptags [i]) {
1119                 case CONSTANT_Class:
1120                         printf("Classreference -> ");
1121                         utf_display(((constant_classref*)e)->name);
1122                         break;
1123                                 
1124                 case CONSTANT_Fieldref:
1125                         printf("Fieldref -> "); goto displayFMIi;
1126                 case CONSTANT_Methodref:
1127                         printf("Methodref -> "); goto displayFMIi;
1128                 case CONSTANT_InterfaceMethodref:
1129                         printf("InterfaceMethod -> "); goto displayFMIi;
1130                 displayFMIi:
1131                         {
1132                                 constant_FMIref *fmi = e;
1133                                 utf_display(fmi->classref->name);
1134                                 printf(".");
1135                                 utf_display(fmi->name);
1136                                 printf(" ");
1137                                 utf_display(fmi->descriptor);
1138                         }
1139                         break;
1140
1141                 case CONSTANT_String:
1142                         printf("String -> ");
1143                         utf_display(e);
1144                         break;
1145                 case CONSTANT_Integer:
1146                         printf("Integer -> %d", (int) (((constant_integer*)e)->value));
1147                         break;
1148                 case CONSTANT_Float:
1149                         printf("Float -> %f", ((constant_float*)e)->value);
1150                         break;
1151                 case CONSTANT_Double:
1152                         printf("Double -> %f", ((constant_double*)e)->value);
1153                         break;
1154                 case CONSTANT_Long:
1155                         {
1156                                 u8 v = ((constant_long*)e)->value;
1157 #if U8_AVAILABLE
1158                                 printf("Long -> %ld", (long int) v);
1159 #else
1160                                 printf("Long -> HI: %ld, LO: %ld\n", 
1161                                             (long int) v.high, (long int) v.low);
1162 #endif 
1163                         }
1164                         break;
1165                 case CONSTANT_NameAndType:
1166                         { 
1167                                 constant_nameandtype *cnt = e;
1168                                 printf("NameAndType: ");
1169                                 utf_display(cnt->name);
1170                                 printf(" ");
1171                                 utf_display(cnt->descriptor);
1172                         }
1173                         break;
1174                 case CONSTANT_Utf8:
1175                         printf("Utf8 -> ");
1176                         utf_display(e);
1177                         break;
1178                 default: 
1179                         log_text("Invalid type of ConstantPool-Entry");
1180                         assert(0);
1181                 }
1182         }
1183         printf("\n");
1184 }
1185
1186
1187 void class_showconstantpool (classinfo *c) 
1188 {
1189         u4 i;
1190         voidptr e;
1191
1192         printf ("---- dump of constant pool ----\n");
1193
1194         for (i=0; i<c->cpcount; i++) {
1195                 printf ("#%d:  ", (int) i);
1196                 
1197                 e = c -> cpinfos [i];
1198                 if (e) {
1199                         
1200                         switch (c -> cptags [i]) {
1201                         case CONSTANT_Class:
1202                                 printf ("Classreference -> ");
1203                                 utf_display ( ((constant_classref*)e) -> name );
1204                                 break;
1205                                 
1206                         case CONSTANT_Fieldref:
1207                                 printf ("Fieldref -> "); goto displayFMI;
1208                         case CONSTANT_Methodref:
1209                                 printf ("Methodref -> "); goto displayFMI;
1210                         case CONSTANT_InterfaceMethodref:
1211                                 printf ("InterfaceMethod -> "); goto displayFMI;
1212                         displayFMI:
1213                                 {
1214                                         constant_FMIref *fmi = e;
1215                                         utf_display ( fmi->classref->name );
1216                                         printf (".");
1217                                         utf_display ( fmi->name);
1218                                         printf (" ");
1219                                         utf_display ( fmi->descriptor );
1220                                 }
1221                                 break;
1222
1223                         case CONSTANT_String:
1224                                 printf ("String -> ");
1225                                 utf_display (e);
1226                                 break;
1227                         case CONSTANT_Integer:
1228                                 printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
1229                                 break;
1230                         case CONSTANT_Float:
1231                                 printf ("Float -> %f", ((constant_float*)e) -> value);
1232                                 break;
1233                         case CONSTANT_Double:
1234                                 printf ("Double -> %f", ((constant_double*)e) -> value);
1235                                 break;
1236                         case CONSTANT_Long:
1237                                 {
1238                                         u8 v = ((constant_long*)e) -> value;
1239 #if U8_AVAILABLE
1240                                         printf ("Long -> %ld", (long int) v);
1241 #else
1242                                         printf ("Long -> HI: %ld, LO: %ld\n", 
1243                                                         (long int) v.high, (long int) v.low);
1244 #endif 
1245                                 }
1246                                 break;
1247                         case CONSTANT_NameAndType:
1248                                 {
1249                                         constant_nameandtype *cnt = e;
1250                                         printf ("NameAndType: ");
1251                                         utf_display (cnt->name);
1252                                         printf (" ");
1253                                         utf_display (cnt->descriptor);
1254                                 }
1255                                 break;
1256                         case CONSTANT_Utf8:
1257                                 printf ("Utf8 -> ");
1258                                 utf_display (e);
1259                                 break;
1260                         default: 
1261                                 log_text("Invalid type of ConstantPool-Entry");
1262                                 assert(0);
1263                         }
1264                 }
1265
1266                 printf ("\n");
1267         }
1268 }
1269
1270
1271
1272 /********** Function: class_showmethods   (debugging only) *************/
1273
1274 void class_showmethods (classinfo *c)
1275 {
1276         s4 i;
1277         
1278         printf ("--------- Fields and Methods ----------------\n");
1279         printf ("Flags: ");     printflags (c->flags);  printf ("\n");
1280
1281         printf ("This: "); utf_display (c->name); printf ("\n");
1282         if (c->super.cls) {
1283                 printf ("Super: "); utf_display (c->super.cls->name); printf ("\n");
1284                 }
1285         printf ("Index: %d\n", c->index);
1286         
1287         printf ("interfaces:\n");       
1288         for (i=0; i < c-> interfacescount; i++) {
1289                 printf ("   ");
1290                 utf_display (c -> interfaces[i].cls -> name);
1291                 printf (" (%d)\n", c->interfaces[i].cls -> index);
1292                 }
1293
1294         printf ("fields:\n");           
1295         for (i=0; i < c -> fieldscount; i++) {
1296                 field_display (&(c -> fields[i]));
1297                 }
1298
1299         printf ("methods:\n");
1300         for (i=0; i < c -> methodscount; i++) {
1301                 methodinfo *m = &(c->methods[i]);
1302                 if ( !(m->flags & ACC_STATIC)) 
1303                         printf ("vftblindex: %d   ", m->vftblindex);
1304
1305                 method_display ( m );
1306
1307                 }
1308
1309         printf ("Virtual function table:\n");
1310         for (i=0; i<c->vftbl->vftbllength; i++) {
1311                 printf ("entry: %d,  %ld\n", i, (long int) (c->vftbl->table[i]) );
1312                 }
1313
1314 }
1315
1316
1317 /*
1318  * These are local overrides for various environment variables in Emacs.
1319  * Please do not remove this and leave it at the end of the file, where
1320  * Emacs will automagically detect them.
1321  * ---------------------------------------------------------------------
1322  * Local variables:
1323  * mode: c
1324  * indent-tabs-mode: t
1325  * c-basic-offset: 4
1326  * tab-width: 4
1327  * End:
1328  */