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