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