d191532ae9fa2553ec030d5f8e6964e9ffdf949f
[cacao.git] / src / vm / class.c
1 /* src/vm/class.c - class related functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28
29    Changes: Mark Probst
30             Andreas Krall
31             Christian Thalinger
32
33    $Id: class.c 2193 2005-04-02 19:33:43Z edwin $
34
35 */
36
37 #include <assert.h>
38 #include <string.h>
39
40 #include "vm/global.h"
41 #include "mm/memory.h"
42
43 #if defined(USE_THREADS)
44 # if defined(NATIVE_THREADS)
45 #  include "threads/native/threads.h"
46 # else
47 #  include "threads/green/threads.h"
48 #  include "threads/green/locks.h"
49 # endif
50 #endif
51
52 #include "toolbox/logging.h"
53 #include "vm/class.h"
54 #include "vm/options.h"
55 #include "vm/resolve.h"
56 #include "vm/statistics.h"
57 #include "vm/tables.h"
58 #include "vm/utf8.h"
59 #include "vm/loader.h"
60
61
62 /******************************************************************************/
63 /* DEBUG HELPERS                                                              */
64 /******************************************************************************/
65
66 #ifndef NDEBUG
67 #define CLASS_DEBUG
68 #endif
69
70 #ifdef CLASS_DEBUG
71 #define CLASS_ASSERT(cond)  assert(cond)
72 #else
73 #define CLASS_ASSERT(cond)
74 #endif
75
76
77 /* global variables ***********************************************************/
78
79 hashtable class_hash;                   /* hashtable for classes              */
80
81 list unlinkedclasses;                   /* this is only used for eager class  */
82                                         /* loading                            */
83
84
85 /* frequently used classes ****************************************************/
86
87 /* important system classes */
88
89 classinfo *class_java_lang_Object = NULL;
90 classinfo *class_java_lang_Class = NULL;
91 classinfo *class_java_lang_ClassLoader = NULL;
92 classinfo *class_java_lang_Cloneable = NULL;
93 classinfo *class_java_lang_SecurityManager = NULL;
94 classinfo *class_java_lang_String = NULL;
95 classinfo *class_java_lang_System = NULL;
96 classinfo *class_java_io_Serializable = NULL;
97
98
99 /* system exception classes required in cacao */
100
101 classinfo *class_java_lang_Throwable = NULL;
102 classinfo *class_java_lang_VMThrowable = NULL;
103 classinfo *class_java_lang_Exception = NULL;
104 classinfo *class_java_lang_Error = NULL;
105 classinfo *class_java_lang_OutOfMemoryError = NULL;
106 classinfo *class_java_lang_NoClassDefFoundError = NULL;
107
108 classinfo *class_java_lang_Void = NULL;
109 classinfo *class_java_lang_Boolean = NULL;
110 classinfo *class_java_lang_Byte = NULL;
111 classinfo *class_java_lang_Character = NULL;
112 classinfo *class_java_lang_Short = NULL;
113 classinfo *class_java_lang_Integer = NULL;
114 classinfo *class_java_lang_Long = NULL;
115 classinfo *class_java_lang_Float = NULL;
116 classinfo *class_java_lang_Double = NULL;
117
118 /* some classes which may be used more often */
119
120 classinfo *class_java_util_Vector = NULL;
121
122
123 /* pseudo classes for the typechecker */
124
125 classinfo *pseudo_class_Arraystub = NULL;
126 classinfo *pseudo_class_Null = NULL;
127 classinfo *pseudo_class_New = NULL;
128
129 /* class_new *******************************************************************
130
131    Searches for the class with the specified name in the classes
132    hashtable, if there is no such class a new classinfo structure is
133    created and inserted into the list of classes to be loaded.
134
135 *******************************************************************************/
136
137 classinfo *class_new(utf *classname)
138 {
139     classinfo *c;
140
141 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
142     tables_lock();
143 #endif
144
145         /* we support eager class loading and linking on demand */
146         if (opt_eager) {
147                 classinfo *tc;
148                 classinfo *tmp;
149
150                 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
151
152                 if (!load_class_bootstrap(classname,&c)) {
153 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
154                         tables_unlock();
155 #endif
156                         return NULL;
157                 }
158
159                 /* link all referenced classes */
160
161                 tc = list_first(&unlinkedclasses);
162
163                 while (tc) {
164                         /* skip the current loaded/linked class */
165                         if (tc != c) {
166                                 if (!link_class(tc)) {
167 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
168                                         tables_unlock();
169 #endif
170                                         return c;
171                                 }
172                         }
173
174                         /* we need a tmp variable here, because list_remove sets prev and
175                            next to NULL */
176                         tmp = list_next(&unlinkedclasses, tc);
177                         list_remove(&unlinkedclasses, tc);
178                         tc = tmp;
179                 }
180
181                 if (!c->linked) {
182                         if (!link_class(c)) {
183 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
184                                 tables_unlock();
185 #endif
186                                 return c;
187                         }
188                 }
189         }
190         else {
191                 c = class_new_intern(classname);
192         }
193
194
195 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
196     tables_unlock();
197 #endif
198
199     return c;
200 }
201
202
203 classinfo *class_new_intern(utf *classname)
204 {
205         classinfo *c;     /* hashtable element */
206         u4 key;           /* hashkey computed from classname */
207         u4 slot;          /* slot in hashtable */
208         u2 i;
209
210         key  = utf_hashkey(classname->text, classname->blength);
211         slot = key & (class_hash.size - 1);
212         c    = class_hash.ptr[slot];
213
214         /* search external hash chain for the class */
215         while (c) {
216                 if (c->name->blength == classname->blength) {
217                         for (i = 0; i < classname->blength; i++)
218                                 if (classname->text[i] != c->name->text[i]) goto nomatch;
219                                                 
220                         /* class found in hashtable */
221                         return c;
222                 }
223                         
224         nomatch:
225                 c = c->hashlink; /* next element in external chain */
226         }
227
228         /* location in hashtable found, create new classinfo structure */
229
230 #if defined(STATISTICS)
231         if (opt_stat)
232                 count_class_infos += sizeof(classinfo);
233 #endif
234
235         if (initverbose) {
236                 char logtext[MAXLOGTEXT];
237                 sprintf(logtext, "Creating class: ");
238                 utf_sprint_classname(logtext + strlen(logtext), classname);
239                 log_text(logtext);
240         }
241
242         c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
243         /*c=NEW(classinfo);*/
244         c->vmClass = 0;
245         c->flags = 0;
246         c->name = classname;
247         c->packagename = NULL;
248         c->cpcount = 0;
249         c->cptags = NULL;
250         c->cpinfos = NULL;
251         c->classrefs = NULL;
252         c->extclassrefs = NULL;
253         c->classrefcount = 0;
254         c->parseddescs = NULL;
255         c->parseddescsize = 0;
256         c->super.any = NULL;
257         c->sub = NULL;
258         c->nextsub = NULL;
259         c->interfacescount = 0;
260         c->interfaces = NULL;
261         c->fieldscount = 0;
262         c->fields = NULL;
263         c->methodscount = 0;
264         c->methods = NULL;
265         c->linked = false;
266         c->loaded = false;
267         c->index = 0;
268         c->instancesize = 0;
269         c->header.vftbl = NULL;
270         c->innerclasscount = 0;
271         c->innerclass = NULL;
272         c->vftbl = NULL;
273         c->initialized = false;
274         c->initializing = false;
275         c->classvftbl = false;
276     c->classUsed = 0;
277     c->impldBy = NULL;
278         c->classloader = NULL;
279         c->sourcefile = NULL;
280         
281         /* insert class into the hashtable */
282         c->hashlink = class_hash.ptr[slot];
283         class_hash.ptr[slot] = c;
284
285         /* update number of hashtable-entries */
286         class_hash.entries++;
287
288         if (class_hash.entries > (class_hash.size * 2)) {
289
290                 /* reorganization of hashtable, average length of 
291                    the external chains is approx. 2                */  
292
293                 u4 i;
294                 classinfo *c;
295                 hashtable newhash;  /* the new hashtable */
296
297                 /* create new hashtable, double the size */
298                 init_hashtable(&newhash, class_hash.size * 2);
299                 newhash.entries = class_hash.entries;
300
301                 /* transfer elements to new hashtable */
302                 for (i = 0; i < class_hash.size; i++) {
303                         c = (classinfo *) class_hash.ptr[i];
304                         while (c) {
305                                 classinfo *nextc = c->hashlink;
306                                 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
307                                                 
308                                 c->hashlink = newhash.ptr[slot];
309                                 newhash.ptr[slot] = c;
310
311                                 c = nextc;
312                         }
313                 }
314         
315                 /* dispose old table */ 
316                 MFREE(class_hash.ptr, void*, class_hash.size);
317                 class_hash = newhash;
318         }
319
320         /* Array classes need further initialization. */
321         if (c->name->text[0] == '[') {
322                 /* Array classes are not loaded from classfiles. */
323                 c->loaded = true;
324                 class_new_array(c);
325                 c->packagename = array_packagename;
326
327         } else {
328                 /* Find the package name */
329                 /* Classes in the unnamed package keep packagename == NULL. */
330                 char *p = utf_end(c->name) - 1;
331                 char *start = c->name->text;
332                 for (;p > start; --p) {
333                         if (*p == '/') {
334                                 c->packagename = utf_new (start, p - start);
335                                 break;
336                         }
337                 }
338         }
339
340 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
341         initObjectLock(&c->header);
342 #endif
343
344         return c;
345 }
346
347
348 /* class_get *******************************************************************
349
350    Searches for the class with the specified name in the classes
351    hashtable if there is no such class NULL is returned.
352
353 *******************************************************************************/
354
355 classinfo *class_get(utf *classname)
356 {
357         classinfo *c;  /* hashtable element */ 
358         u4 key;        /* hashkey computed from classname */   
359         u4 slot;       /* slot in hashtable */
360         u2 i;  
361
362         key  = utf_hashkey(classname->text, classname->blength);
363         slot = key & (class_hash.size-1);
364         c    = class_hash.ptr[slot];
365
366         /* search external hash-chain */
367         while (c) {
368                 if (c->name->blength == classname->blength) {
369                         /* compare classnames */
370                         for (i = 0; i < classname->blength; i++) 
371                                 if (classname->text[i] != c->name->text[i])
372                                         goto nomatch;
373
374                         /* class found in hashtable */                          
375                         return c;
376                 }
377                         
378         nomatch:
379                 c = c->hashlink;
380         }
381
382         /* class not found */
383         return NULL;
384 }
385
386
387 /* class_remove ****************************************************************
388
389    Removes the class entry wth the specified name in the classes
390    hashtable, furthermore the class' resources are freed if there is
391    no such class false is returned.
392
393 *******************************************************************************/
394
395 bool class_remove(classinfo *c)
396 {
397         classinfo *tc;                      /* hashtable element                  */
398         classinfo *pc;
399         u4 key;                             /* hashkey computed from classname    */
400         u4 slot;                            /* slot in hashtable                  */
401         u2 i;  
402
403         key  = utf_hashkey(c->name->text, c->name->blength);
404         slot = key & (class_hash.size - 1);
405         tc   = class_hash.ptr[slot];
406         pc   = NULL;
407
408         /* search external hash-chain */
409         while (tc) {
410                 if (tc->name->blength == c->name->blength) {
411                         
412                         /* compare classnames */
413                         for (i = 0; i < c->name->blength; i++)
414                                 if (tc->name->text[i] != c->name->text[i])
415                                         goto nomatch;
416
417                         /* class found in hashtable */
418                         if (!pc)
419                                 class_hash.ptr[slot] = tc->hashlink;
420                         else
421                                 pc->hashlink = tc->hashlink;
422
423                         class_free(tc);
424
425                         return true;
426                 }
427                         
428         nomatch:
429                 pc = tc;
430                 tc = tc->hashlink;
431         }
432
433         /* class not found */
434         return false;
435 }
436
437
438 /* class_freepool **************************************************************
439
440         Frees all resources used by this classes Constant Pool.
441
442 *******************************************************************************/
443
444 static void class_freecpool(classinfo *c)
445 {
446         u4 idx;
447         u4 tag;
448         voidptr info;
449         
450         if (c->cptags && c->cpinfos) {
451                 for (idx = 0; idx < c->cpcount; idx++) {
452                         tag = c->cptags[idx];
453                         info = c->cpinfos[idx];
454                 
455                         if (info != NULL) {
456                                 switch (tag) {
457                                 case CONSTANT_Fieldref:
458                                 case CONSTANT_Methodref:
459                                 case CONSTANT_InterfaceMethodref:
460                                         FREE(info, constant_FMIref);
461                                         break;
462                                 case CONSTANT_Integer:
463                                         FREE(info, constant_integer);
464                                         break;
465                                 case CONSTANT_Float:
466                                         FREE(info, constant_float);
467                                         break;
468                                 case CONSTANT_Long:
469                                         FREE(info, constant_long);
470                                         break;
471                                 case CONSTANT_Double:
472                                         FREE(info, constant_double);
473                                         break;
474                                 case CONSTANT_NameAndType:
475                                         FREE(info, constant_nameandtype);
476                                         break;
477                                 }
478                         }
479                 }
480         }
481
482         if (c->cptags)
483                 MFREE(c->cptags, u1, c->cpcount);
484
485         if (c->cpinfos)
486                 MFREE(c->cpinfos, voidptr, c->cpcount);
487 }
488
489
490 /* class_free ******************************************************************
491
492    Frees all resources used by the class.
493
494 *******************************************************************************/
495
496 void class_free(classinfo *c)
497 {
498         s4 i;
499         vftbl_t *v;
500                 
501         class_freecpool(c);
502
503         if (c->interfaces)
504                 MFREE(c->interfaces, classinfo*, c->interfacescount);
505
506         if (c->fields) {
507                 for (i = 0; i < c->fieldscount; i++)
508                         field_free(&(c->fields[i]));
509 /*      MFREE(c->fields, fieldinfo, c->fieldscount); */
510         }
511         
512         if (c->methods) {
513                 for (i = 0; i < c->methodscount; i++)
514                         method_free(&(c->methods[i]));
515                 MFREE(c->methods, methodinfo, c->methodscount);
516         }
517
518         if ((v = c->vftbl) != NULL) {
519                 if (v->arraydesc)
520                         mem_free(v->arraydesc,sizeof(arraydescriptor));
521                 
522                 for (i = 0; i < v->interfacetablelength; i++) {
523                         MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
524                 }
525                 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
526
527                 i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
528                     sizeof(methodptr*) * (v->interfacetablelength -
529                                          (v->interfacetablelength > 0));
530                 v = (vftbl_t*) (((methodptr*) v) -
531                                                 (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
532                 mem_free(v, i);
533         }
534
535         if (c->innerclass)
536                 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
537
538         /*      if (c->classvftbl)
539                 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
540         
541 /*      GCFREE(c); */
542 }
543
544
545 /* class_array_of **************************************************************
546
547    Returns an array class with the given component class. The array
548    class is dynamically created if neccessary.
549
550 *******************************************************************************/
551
552 classinfo *class_array_of(classinfo *component)
553 {
554     s4 namelen;
555     char *namebuf;
556         classinfo *c;
557
558     /* Assemble the array class name */
559     namelen = component->name->blength;
560     
561     if (component->name->text[0] == '[') {
562         /* the component is itself an array */
563         namebuf = DMNEW(char, namelen + 1);
564         namebuf[0] = '[';
565         MCOPY(namebuf + 1, component->name->text, char, namelen);
566         namelen++;
567
568     } else {
569         /* the component is a non-array class */
570         namebuf = DMNEW(char, namelen + 3);
571         namebuf[0] = '[';
572         namebuf[1] = 'L';
573         MCOPY(namebuf + 2, component->name->text, char, namelen);
574         namebuf[2 + namelen] = ';';
575         namelen += 3;
576     }
577
578         c = class_new(utf_new(namebuf, namelen));
579
580         /* load this class and link it */
581
582         c->loaded = true;
583
584         if (!c->linked)
585                 if (!link_class(c))
586                         return NULL;
587
588     return c;
589 }
590
591
592 /* class_multiarray_of *********************************************************
593
594    Returns an array class with the given dimension and element class.
595    The array class is dynamically created if neccessary.
596
597 *******************************************************************************/
598
599 classinfo *class_multiarray_of(s4 dim, classinfo *element)
600 {
601     s4 namelen;
602     char *namebuf;
603
604         if (dim < 1)
605                 panic("Invalid array dimension requested");
606
607     /* Assemble the array class name */
608     namelen = element->name->blength;
609     
610     if (element->name->text[0] == '[') {
611         /* the element is itself an array */
612         namebuf = DMNEW(char, namelen + dim);
613         memcpy(namebuf + dim, element->name->text, namelen);
614         namelen += dim;
615     }
616     else {
617         /* the element is a non-array class */
618         namebuf = DMNEW(char, namelen + 2 + dim);
619         namebuf[dim] = 'L';
620         memcpy(namebuf + dim + 1, element->name->text, namelen);
621         namelen += (2 + dim);
622         namebuf[namelen - 1] = ';';
623     }
624         memset(namebuf, '[', dim);
625
626     return class_new(utf_new(namebuf, namelen));
627 }
628
629 /* class_lookup_classref *******************************************************
630
631    Looks up the constant_classref for a given classname in the classref
632    tables of a class.
633
634    IN:
635        cls..............the class containing the reference
636            name.............the name of the class refered to
637
638     RETURN VALUE:
639            a pointer to a constant_classref, or 
640            NULL if the reference was not found
641    
642 *******************************************************************************/
643
644 constant_classref *class_lookup_classref(classinfo *cls,utf *name)
645 {
646         constant_classref *ref;
647         extra_classref *xref;
648         int count;
649
650         CLASS_ASSERT(cls);
651         CLASS_ASSERT(name);
652         CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
653         
654         /* first search the main classref table */
655         count = cls->classrefcount;
656         ref = cls->classrefs;
657         for (; count; --count, ++ref)
658                 if (ref->name == name)
659                         return ref;
660
661         /* next try the list of extra classrefs */
662         for (xref=cls->extclassrefs; xref; xref=xref->next) {
663                 if (xref->classref.name == name)
664                         return &(xref->classref);
665         }
666
667         /* not found */
668         return NULL;
669 }
670
671
672 /* class_get_classref **********************************************************
673
674    Returns the constant_classref for a given classname.
675
676    IN:
677        cls..............the class containing the reference
678            name.............the name of the class refered to
679
680    RETURN VALUE:
681        a pointer to a constant_classref (never NULL)
682
683    NOTE:
684        The given name is not checked for validity!
685    
686 *******************************************************************************/
687
688 constant_classref *class_get_classref(classinfo *cls,utf *name)
689 {
690         constant_classref *ref;
691         extra_classref *xref;
692
693         CLASS_ASSERT(cls);
694         CLASS_ASSERT(name);
695
696         ref = class_lookup_classref(cls,name);
697         if (ref)
698                 return ref;
699
700         xref = NEW(extra_classref);
701         CLASSREF_INIT(xref->classref,cls,name);
702
703         xref->next = cls->extclassrefs;
704         cls->extclassrefs = xref;
705
706         return &(xref->classref);
707 }
708
709 /* class_get_classref_multiarray_of ********************************************
710
711    Returns an array type reference with the given dimension and element class
712    reference.
713
714    IN:
715        dim..............the requested dimension
716                             dim must be in [1;255]. This is NOT checked!
717            ref..............the component class reference
718
719    RETURN VALUE:
720        a pointer to the class reference for the array type
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_multiarray_of(s4 dim,constant_classref *ref)
728 {
729     s4 namelen;
730     char *namebuf;
731
732         CLASS_ASSERT(ref);
733         CLASS_ASSERT(dim >= 1 && dim <= 255);
734
735     /* Assemble the array class name */
736     namelen = ref->name->blength;
737     
738     if (ref->name->text[0] == '[') {
739         /* the element is itself an array */
740         namebuf = DMNEW(char, namelen + dim);
741         memcpy(namebuf + dim, ref->name->text, namelen);
742         namelen += dim;
743     }
744     else {
745         /* the element is a non-array class */
746         namebuf = DMNEW(char, namelen + 2 + dim);
747         namebuf[dim] = 'L';
748         memcpy(namebuf + dim + 1, ref->name->text, namelen);
749         namelen += (2 + dim);
750         namebuf[namelen - 1] = ';';
751     }
752         memset(namebuf, '[', dim);
753
754     return class_get_classref(ref->referer,utf_new(namebuf, namelen));
755 }
756
757 /* class_get_classref_component_of *********************************************
758
759    Returns the component classref of a given array type reference
760
761    IN:
762        ref..............the array type reference
763
764    RETURN VALUE:
765        a reference to the component class, or
766            NULL if `ref` is not an object array type reference
767
768    NOTE:
769        The referer of `ref` is used as the referer for the new classref.
770
771 *******************************************************************************/
772
773 constant_classref *class_get_classref_component_of(constant_classref *ref)
774 {
775         s4 namelen;
776         char *name;
777         
778         CLASS_ASSERT(ref);
779
780         name = ref->name->text;
781         if (*name++ != '[')
782                 return NULL;
783         
784         namelen = ref->name->blength - 1;
785         if (*name == 'L') {
786                 name++;
787                 namelen -= 2;
788         }
789         else if (*name != '[') {
790                 return NULL;
791         }
792
793     return class_get_classref(ref->referer,utf_new(name, namelen));
794 }
795
796
797 /*
798  * These are local overrides for various environment variables in Emacs.
799  * Please do not remove this and leave it at the end of the file, where
800  * Emacs will automagically detect them.
801  * ---------------------------------------------------------------------
802  * Local variables:
803  * mode: c
804  * indent-tabs-mode: t
805  * c-basic-offset: 4
806  * tab-width: 4
807  * End:
808  */