1 /* src/vm/class.c - class related functions
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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
33 $Id: class.c 2148 2005-03-30 16:49:40Z twisti $
43 #include "mm/memory.h"
45 #if defined(USE_THREADS)
46 # if defined(NATIVE_THREADS)
47 # include "threads/native/threads.h"
49 # include "threads/green/threads.h"
50 # include "threads/green/locks.h"
54 #include "toolbox/logging.h"
56 #include "vm/options.h"
57 #include "vm/resolve.h"
58 #include "vm/statistics.h"
59 #include "vm/tables.h"
63 /******************************************************************************/
65 /******************************************************************************/
72 #define CLASS_ASSERT(cond) assert(cond)
74 #define CLASS_ASSERT(cond)
78 /* global variables ***********************************************************/
80 hashtable class_hash; /* hashtable for classes */
82 list unlinkedclasses; /* this is only used for eager class */
86 /* frequently used classes ****************************************************/
88 /* important system classes */
90 classinfo *class_java_lang_Object;
91 classinfo *class_java_lang_Class;
92 classinfo *class_java_lang_ClassLoader;
93 classinfo *class_java_lang_Cloneable;
94 classinfo *class_java_lang_SecurityManager;
95 classinfo *class_java_lang_String;
96 classinfo *class_java_lang_System;
97 classinfo *class_java_io_Serializable;
100 /* system exception classes required in cacao */
102 classinfo *class_java_lang_Throwable;
103 classinfo *class_java_lang_VMThrowable;
104 classinfo *class_java_lang_Exception;
105 classinfo *class_java_lang_Error;
106 classinfo *class_java_lang_OutOfMemoryError;
109 classinfo *class_java_lang_Void;
110 classinfo *class_java_lang_Boolean;
111 classinfo *class_java_lang_Byte;
112 classinfo *class_java_lang_Character;
113 classinfo *class_java_lang_Short;
114 classinfo *class_java_lang_Integer;
115 classinfo *class_java_lang_Long;
116 classinfo *class_java_lang_Float;
117 classinfo *class_java_lang_Double;
119 /* some classes which may be used more often */
121 classinfo *class_java_util_Vector;
124 /* pseudo classes for the typechecker */
126 classinfo *pseudo_class_Arraystub;
127 classinfo *pseudo_class_Null;
128 classinfo *pseudo_class_New;
131 /* class_init ******************************************************************
133 Initialize the class subsystem.
135 *******************************************************************************/
137 void class_init_foo(void)
139 class_java_lang_Object = class_new_intern(utf_java_lang_Object);
141 class_java_lang_Class = class_new(utf_java_lang_Class);
142 class_java_lang_ClassLoader = class_new(utf_java_lang_ClassLoader);
143 class_java_lang_Cloneable = class_new(utf_java_lang_Cloneable);
144 class_java_lang_SecurityManager = class_new(utf_java_lang_SecurityManager);
145 class_java_lang_String = class_new(utf_java_lang_String);
146 class_java_lang_System = class_new(utf_java_lang_System);
147 class_java_io_Serializable = class_new(utf_java_io_Serializable);
149 class_java_lang_Throwable = class_new(utf_java_lang_Throwable);
150 class_java_lang_VMThrowable = class_new(utf_java_lang_VMThrowable);
151 class_java_lang_Exception = class_new(utf_java_lang_Exception);
152 class_java_lang_Error = class_new(utf_java_lang_Error);
153 class_java_lang_OutOfMemoryError =
154 class_new(utf_java_lang_OutOfMemoryError);
156 class_java_lang_Void = class_new(utf_java_lang_Void);
157 class_java_lang_Boolean = class_new(utf_java_lang_Boolean);
158 class_java_lang_Byte = class_new(utf_java_lang_Byte);
159 class_java_lang_Character = class_new(utf_java_lang_Character);
160 class_java_lang_Short = class_new(utf_java_lang_Short);
161 class_java_lang_Integer = class_new(utf_java_lang_Integer);
162 class_java_lang_Long = class_new(utf_java_lang_Long);
163 class_java_lang_Float = class_new(utf_java_lang_Float);
164 class_java_lang_Double = class_new(utf_java_lang_Double);
166 class_java_util_Vector = class_new(utf_java_util_Vector);
168 pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
169 pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
170 pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
174 /* class_new *******************************************************************
176 Searches for the class with the specified name in the classes
177 hashtable, if there is no such class a new classinfo structure is
178 created and inserted into the list of classes to be loaded.
180 *******************************************************************************/
182 classinfo *class_new(utf *classname)
186 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
190 c = class_new_intern(classname);
192 /* we support eager class loading and linking on demand */
198 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
201 if (!load_class_bootstrap(c)) {
202 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
209 /* link all referenced classes */
211 tc = list_first(&unlinkedclasses);
214 /* skip the current loaded/linked class */
216 if (!link_class(tc)) {
217 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
224 /* we need a tmp variable here, because list_remove sets prev and
226 tmp = list_next(&unlinkedclasses, tc);
227 list_remove(&unlinkedclasses, tc);
232 if (!link_class(c)) {
233 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
241 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
249 classinfo *class_new_intern(utf *classname)
251 classinfo *c; /* hashtable element */
252 u4 key; /* hashkey computed from classname */
253 u4 slot; /* slot in hashtable */
256 key = utf_hashkey(classname->text, classname->blength);
257 slot = key & (class_hash.size - 1);
258 c = class_hash.ptr[slot];
260 /* search external hash chain for the class */
262 if (c->name->blength == classname->blength) {
263 for (i = 0; i < classname->blength; i++)
264 if (classname->text[i] != c->name->text[i]) goto nomatch;
266 /* class found in hashtable */
271 c = c->hashlink; /* next element in external chain */
274 /* location in hashtable found, create new classinfo structure */
276 #if defined(STATISTICS)
278 count_class_infos += sizeof(classinfo);
282 char logtext[MAXLOGTEXT];
283 sprintf(logtext, "Creating class: ");
284 utf_sprint_classname(logtext + strlen(logtext), classname);
288 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
289 /*c=NEW(classinfo);*/
293 c->packagename = NULL;
298 c->extclassrefs = NULL;
299 c->classrefcount = 0;
300 c->parseddescs = NULL;
301 c->parseddescsize = 0;
305 c->interfacescount = 0;
306 c->interfaces = NULL;
315 c->header.vftbl = NULL;
316 c->innerclasscount = 0;
317 c->innerclass = NULL;
319 c->initialized = false;
320 c->initializing = false;
321 c->classvftbl = false;
324 c->classloader = NULL;
325 c->sourcefile = NULL;
327 /* insert class into the hashtable */
328 c->hashlink = class_hash.ptr[slot];
329 class_hash.ptr[slot] = c;
331 /* update number of hashtable-entries */
332 class_hash.entries++;
334 if (class_hash.entries > (class_hash.size * 2)) {
336 /* reorganization of hashtable, average length of
337 the external chains is approx. 2 */
341 hashtable newhash; /* the new hashtable */
343 /* create new hashtable, double the size */
344 init_hashtable(&newhash, class_hash.size * 2);
345 newhash.entries = class_hash.entries;
347 /* transfer elements to new hashtable */
348 for (i = 0; i < class_hash.size; i++) {
349 c = (classinfo *) class_hash.ptr[i];
351 classinfo *nextc = c->hashlink;
352 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
354 c->hashlink = newhash.ptr[slot];
355 newhash.ptr[slot] = c;
361 /* dispose old table */
362 MFREE(class_hash.ptr, void*, class_hash.size);
363 class_hash = newhash;
366 /* Array classes need further initialization. */
367 if (c->name->text[0] == '[') {
368 /* Array classes are not loaded from classfiles. */
371 c->packagename = array_packagename;
374 /* Find the package name */
375 /* Classes in the unnamed package keep packagename == NULL. */
376 char *p = utf_end(c->name) - 1;
377 char *start = c->name->text;
378 for (;p > start; --p) {
380 c->packagename = utf_new (start, p - start);
386 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
387 initObjectLock(&c->header);
394 /* class_get *******************************************************************
396 Searches for the class with the specified name in the classes
397 hashtable if there is no such class NULL is returned.
399 *******************************************************************************/
401 classinfo *class_get(utf *classname)
403 classinfo *c; /* hashtable element */
404 u4 key; /* hashkey computed from classname */
405 u4 slot; /* slot in hashtable */
408 key = utf_hashkey(classname->text, classname->blength);
409 slot = key & (class_hash.size-1);
410 c = class_hash.ptr[slot];
412 /* search external hash-chain */
414 if (c->name->blength == classname->blength) {
415 /* compare classnames */
416 for (i = 0; i < classname->blength; i++)
417 if (classname->text[i] != c->name->text[i])
420 /* class found in hashtable */
428 /* class not found */
433 /* class_remove ****************************************************************
435 Removes the class entry wth the specified name in the classes
436 hashtable, furthermore the class' resources are freed if there is
437 no such class false is returned.
439 *******************************************************************************/
441 bool class_remove(classinfo *c)
443 classinfo *tc; /* hashtable element */
445 u4 key; /* hashkey computed from classname */
446 u4 slot; /* slot in hashtable */
449 key = utf_hashkey(c->name->text, c->name->blength);
450 slot = key & (class_hash.size - 1);
451 tc = class_hash.ptr[slot];
454 /* search external hash-chain */
456 if (tc->name->blength == c->name->blength) {
458 /* compare classnames */
459 for (i = 0; i < c->name->blength; i++)
460 if (tc->name->text[i] != c->name->text[i])
463 /* class found in hashtable */
465 class_hash.ptr[slot] = tc->hashlink;
467 pc->hashlink = tc->hashlink;
479 /* class not found */
484 /* class_freepool **************************************************************
486 Frees all resources used by this classes Constant Pool.
488 *******************************************************************************/
490 static void class_freecpool(classinfo *c)
496 if (c->cptags && c->cpinfos) {
497 for (idx = 0; idx < c->cpcount; idx++) {
498 tag = c->cptags[idx];
499 info = c->cpinfos[idx];
503 case CONSTANT_Fieldref:
504 case CONSTANT_Methodref:
505 case CONSTANT_InterfaceMethodref:
506 FREE(info, constant_FMIref);
508 case CONSTANT_Integer:
509 FREE(info, constant_integer);
512 FREE(info, constant_float);
515 FREE(info, constant_long);
517 case CONSTANT_Double:
518 FREE(info, constant_double);
520 case CONSTANT_NameAndType:
521 FREE(info, constant_nameandtype);
529 MFREE(c->cptags, u1, c->cpcount);
532 MFREE(c->cpinfos, voidptr, c->cpcount);
536 /* class_free ******************************************************************
538 Frees all resources used by the class.
540 *******************************************************************************/
542 void class_free(classinfo *c)
550 MFREE(c->interfaces, classinfo*, c->interfacescount);
553 for (i = 0; i < c->fieldscount; i++)
554 field_free(&(c->fields[i]));
555 /* MFREE(c->fields, fieldinfo, c->fieldscount); */
559 for (i = 0; i < c->methodscount; i++)
560 method_free(&(c->methods[i]));
561 MFREE(c->methods, methodinfo, c->methodscount);
564 if ((v = c->vftbl) != NULL) {
566 mem_free(v->arraydesc,sizeof(arraydescriptor));
568 for (i = 0; i < v->interfacetablelength; i++) {
569 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
571 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
573 i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
574 sizeof(methodptr*) * (v->interfacetablelength -
575 (v->interfacetablelength > 0));
576 v = (vftbl_t*) (((methodptr*) v) -
577 (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
582 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
584 /* if (c->classvftbl)
585 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
591 /* class_array_of **************************************************************
593 Returns an array class with the given component class. The array
594 class is dynamically created if neccessary.
596 *******************************************************************************/
598 classinfo *class_array_of(classinfo *component)
604 /* Assemble the array class name */
605 namelen = component->name->blength;
607 if (component->name->text[0] == '[') {
608 /* the component is itself an array */
609 namebuf = DMNEW(char, namelen + 1);
611 MCOPY(namebuf + 1, component->name->text, char, namelen);
615 /* the component is a non-array class */
616 namebuf = DMNEW(char, namelen + 3);
619 MCOPY(namebuf + 2, component->name->text, char, namelen);
620 namebuf[2 + namelen] = ';';
624 c = class_new(utf_new(namebuf, namelen));
626 /* load this class and link it */
638 /* class_multiarray_of *********************************************************
640 Returns an array class with the given dimension and element class.
641 The array class is dynamically created if neccessary.
643 *******************************************************************************/
645 classinfo *class_multiarray_of(s4 dim, classinfo *element)
651 panic("Invalid array dimension requested");
653 /* Assemble the array class name */
654 namelen = element->name->blength;
656 if (element->name->text[0] == '[') {
657 /* the element is itself an array */
658 namebuf = DMNEW(char, namelen + dim);
659 memcpy(namebuf + dim, element->name->text, namelen);
663 /* the element is a non-array class */
664 namebuf = DMNEW(char, namelen + 2 + dim);
666 memcpy(namebuf + dim + 1, element->name->text, namelen);
667 namelen += (2 + dim);
668 namebuf[namelen - 1] = ';';
670 memset(namebuf, '[', dim);
672 return class_new(utf_new(namebuf, namelen));
675 /* class_lookup_classref *******************************************************
677 Looks up the constant_classref for a given classname in the classref
681 cls..............the class containing the reference
682 name.............the name of the class refered to
685 a pointer to a constant_classref, or
686 NULL if the reference was not found
688 *******************************************************************************/
690 constant_classref *class_lookup_classref(classinfo *cls,utf *name)
692 constant_classref *ref;
693 extra_classref *xref;
698 CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
700 /* first search the main classref table */
701 count = cls->classrefcount;
702 ref = cls->classrefs;
703 for (; count; --count, ++ref)
704 if (ref->name == name)
707 /* next try the list of extra classrefs */
708 for (xref=cls->extclassrefs; xref; xref=xref->next) {
709 if (xref->classref.name == name)
710 return &(xref->classref);
718 /* class_get_classref **********************************************************
720 Returns the constant_classref for a given classname.
723 cls..............the class containing the reference
724 name.............the name of the class refered to
727 a pointer to a constant_classref (never NULL)
730 The given name is not checked for validity!
732 *******************************************************************************/
734 constant_classref *class_get_classref(classinfo *cls,utf *name)
736 constant_classref *ref;
737 extra_classref *xref;
742 ref = class_lookup_classref(cls,name);
746 xref = NEW(extra_classref);
747 CLASSREF_INIT(xref->classref,cls,name);
749 xref->next = cls->extclassrefs;
750 cls->extclassrefs = xref;
752 return &(xref->classref);
755 /* class_get_classref_multiarray_of ********************************************
757 Returns an array type reference with the given dimension and element class
761 dim..............the requested dimension
762 dim must be in [1;255]. This is NOT checked!
763 ref..............the component class reference
766 a pointer to the class reference for the array type
769 The referer of `ref` is used as the referer for the new classref.
771 *******************************************************************************/
773 constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref)
779 CLASS_ASSERT(dim >= 1 && dim <= 255);
781 /* Assemble the array class name */
782 namelen = ref->name->blength;
784 if (ref->name->text[0] == '[') {
785 /* the element is itself an array */
786 namebuf = DMNEW(char, namelen + dim);
787 memcpy(namebuf + dim, ref->name->text, namelen);
791 /* the element is a non-array class */
792 namebuf = DMNEW(char, namelen + 2 + dim);
794 memcpy(namebuf + dim + 1, ref->name->text, namelen);
795 namelen += (2 + dim);
796 namebuf[namelen - 1] = ';';
798 memset(namebuf, '[', dim);
800 return class_get_classref(ref->referer,utf_new(namebuf, namelen));
803 /* class_get_classref_component_of *********************************************
805 Returns the component classref of a given array type reference
808 ref..............the array type reference
811 a reference to the component class, or
812 NULL if `ref` is not an object array type reference
815 The referer of `ref` is used as the referer for the new classref.
817 *******************************************************************************/
819 constant_classref *class_get_classref_component_of(constant_classref *ref)
826 name = ref->name->text;
830 namelen = ref->name->blength - 1;
835 else if (*name != '[') {
839 return class_get_classref(ref->referer,utf_new(name, namelen));
844 * These are local overrides for various environment variables in Emacs.
845 * Please do not remove this and leave it at the end of the file, where
846 * Emacs will automagically detect them.
847 * ---------------------------------------------------------------------
850 * indent-tabs-mode: t