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