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 2153 2005-03-30 19:30:05Z 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;
107 classinfo *class_java_lang_NoClassDefFoundError;
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);
154 class_java_lang_OutOfMemoryError =
155 class_new(utf_java_lang_OutOfMemoryError);
157 class_java_lang_NoClassDefFoundError =
158 class_new(utf_java_lang_NoClassDefFoundError);
160 class_java_lang_Void = class_new(utf_java_lang_Void);
161 class_java_lang_Boolean = class_new(utf_java_lang_Boolean);
162 class_java_lang_Byte = class_new(utf_java_lang_Byte);
163 class_java_lang_Character = class_new(utf_java_lang_Character);
164 class_java_lang_Short = class_new(utf_java_lang_Short);
165 class_java_lang_Integer = class_new(utf_java_lang_Integer);
166 class_java_lang_Long = class_new(utf_java_lang_Long);
167 class_java_lang_Float = class_new(utf_java_lang_Float);
168 class_java_lang_Double = class_new(utf_java_lang_Double);
170 class_java_util_Vector = class_new(utf_java_util_Vector);
172 pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
173 pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
174 pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
178 /* class_new *******************************************************************
180 Searches for the class with the specified name in the classes
181 hashtable, if there is no such class a new classinfo structure is
182 created and inserted into the list of classes to be loaded.
184 *******************************************************************************/
186 classinfo *class_new(utf *classname)
190 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
194 c = class_new_intern(classname);
196 /* we support eager class loading and linking on demand */
202 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
205 if (!load_class_bootstrap(c)) {
206 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
213 /* link all referenced classes */
215 tc = list_first(&unlinkedclasses);
218 /* skip the current loaded/linked class */
220 if (!link_class(tc)) {
221 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
228 /* we need a tmp variable here, because list_remove sets prev and
230 tmp = list_next(&unlinkedclasses, tc);
231 list_remove(&unlinkedclasses, tc);
236 if (!link_class(c)) {
237 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
245 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
253 classinfo *class_new_intern(utf *classname)
255 classinfo *c; /* hashtable element */
256 u4 key; /* hashkey computed from classname */
257 u4 slot; /* slot in hashtable */
260 key = utf_hashkey(classname->text, classname->blength);
261 slot = key & (class_hash.size - 1);
262 c = class_hash.ptr[slot];
264 /* search external hash chain for the class */
266 if (c->name->blength == classname->blength) {
267 for (i = 0; i < classname->blength; i++)
268 if (classname->text[i] != c->name->text[i]) goto nomatch;
270 /* class found in hashtable */
275 c = c->hashlink; /* next element in external chain */
278 /* location in hashtable found, create new classinfo structure */
280 #if defined(STATISTICS)
282 count_class_infos += sizeof(classinfo);
286 char logtext[MAXLOGTEXT];
287 sprintf(logtext, "Creating class: ");
288 utf_sprint_classname(logtext + strlen(logtext), classname);
292 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
293 /*c=NEW(classinfo);*/
297 c->packagename = NULL;
302 c->extclassrefs = NULL;
303 c->classrefcount = 0;
304 c->parseddescs = NULL;
305 c->parseddescsize = 0;
309 c->interfacescount = 0;
310 c->interfaces = NULL;
319 c->header.vftbl = NULL;
320 c->innerclasscount = 0;
321 c->innerclass = NULL;
323 c->initialized = false;
324 c->initializing = false;
325 c->classvftbl = false;
328 c->classloader = NULL;
329 c->sourcefile = NULL;
331 /* insert class into the hashtable */
332 c->hashlink = class_hash.ptr[slot];
333 class_hash.ptr[slot] = c;
335 /* update number of hashtable-entries */
336 class_hash.entries++;
338 if (class_hash.entries > (class_hash.size * 2)) {
340 /* reorganization of hashtable, average length of
341 the external chains is approx. 2 */
345 hashtable newhash; /* the new hashtable */
347 /* create new hashtable, double the size */
348 init_hashtable(&newhash, class_hash.size * 2);
349 newhash.entries = class_hash.entries;
351 /* transfer elements to new hashtable */
352 for (i = 0; i < class_hash.size; i++) {
353 c = (classinfo *) class_hash.ptr[i];
355 classinfo *nextc = c->hashlink;
356 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
358 c->hashlink = newhash.ptr[slot];
359 newhash.ptr[slot] = c;
365 /* dispose old table */
366 MFREE(class_hash.ptr, void*, class_hash.size);
367 class_hash = newhash;
370 /* Array classes need further initialization. */
371 if (c->name->text[0] == '[') {
372 /* Array classes are not loaded from classfiles. */
375 c->packagename = array_packagename;
378 /* Find the package name */
379 /* Classes in the unnamed package keep packagename == NULL. */
380 char *p = utf_end(c->name) - 1;
381 char *start = c->name->text;
382 for (;p > start; --p) {
384 c->packagename = utf_new (start, p - start);
390 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
391 initObjectLock(&c->header);
398 /* class_get *******************************************************************
400 Searches for the class with the specified name in the classes
401 hashtable if there is no such class NULL is returned.
403 *******************************************************************************/
405 classinfo *class_get(utf *classname)
407 classinfo *c; /* hashtable element */
408 u4 key; /* hashkey computed from classname */
409 u4 slot; /* slot in hashtable */
412 key = utf_hashkey(classname->text, classname->blength);
413 slot = key & (class_hash.size-1);
414 c = class_hash.ptr[slot];
416 /* search external hash-chain */
418 if (c->name->blength == classname->blength) {
419 /* compare classnames */
420 for (i = 0; i < classname->blength; i++)
421 if (classname->text[i] != c->name->text[i])
424 /* class found in hashtable */
432 /* class not found */
437 /* class_remove ****************************************************************
439 Removes the class entry wth the specified name in the classes
440 hashtable, furthermore the class' resources are freed if there is
441 no such class false is returned.
443 *******************************************************************************/
445 bool class_remove(classinfo *c)
447 classinfo *tc; /* hashtable element */
449 u4 key; /* hashkey computed from classname */
450 u4 slot; /* slot in hashtable */
453 key = utf_hashkey(c->name->text, c->name->blength);
454 slot = key & (class_hash.size - 1);
455 tc = class_hash.ptr[slot];
458 /* search external hash-chain */
460 if (tc->name->blength == c->name->blength) {
462 /* compare classnames */
463 for (i = 0; i < c->name->blength; i++)
464 if (tc->name->text[i] != c->name->text[i])
467 /* class found in hashtable */
469 class_hash.ptr[slot] = tc->hashlink;
471 pc->hashlink = tc->hashlink;
483 /* class not found */
488 /* class_freepool **************************************************************
490 Frees all resources used by this classes Constant Pool.
492 *******************************************************************************/
494 static void class_freecpool(classinfo *c)
500 if (c->cptags && c->cpinfos) {
501 for (idx = 0; idx < c->cpcount; idx++) {
502 tag = c->cptags[idx];
503 info = c->cpinfos[idx];
507 case CONSTANT_Fieldref:
508 case CONSTANT_Methodref:
509 case CONSTANT_InterfaceMethodref:
510 FREE(info, constant_FMIref);
512 case CONSTANT_Integer:
513 FREE(info, constant_integer);
516 FREE(info, constant_float);
519 FREE(info, constant_long);
521 case CONSTANT_Double:
522 FREE(info, constant_double);
524 case CONSTANT_NameAndType:
525 FREE(info, constant_nameandtype);
533 MFREE(c->cptags, u1, c->cpcount);
536 MFREE(c->cpinfos, voidptr, c->cpcount);
540 /* class_free ******************************************************************
542 Frees all resources used by the class.
544 *******************************************************************************/
546 void class_free(classinfo *c)
554 MFREE(c->interfaces, classinfo*, c->interfacescount);
557 for (i = 0; i < c->fieldscount; i++)
558 field_free(&(c->fields[i]));
559 /* MFREE(c->fields, fieldinfo, c->fieldscount); */
563 for (i = 0; i < c->methodscount; i++)
564 method_free(&(c->methods[i]));
565 MFREE(c->methods, methodinfo, c->methodscount);
568 if ((v = c->vftbl) != NULL) {
570 mem_free(v->arraydesc,sizeof(arraydescriptor));
572 for (i = 0; i < v->interfacetablelength; i++) {
573 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
575 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
577 i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
578 sizeof(methodptr*) * (v->interfacetablelength -
579 (v->interfacetablelength > 0));
580 v = (vftbl_t*) (((methodptr*) v) -
581 (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
586 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
588 /* if (c->classvftbl)
589 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
595 /* class_array_of **************************************************************
597 Returns an array class with the given component class. The array
598 class is dynamically created if neccessary.
600 *******************************************************************************/
602 classinfo *class_array_of(classinfo *component)
608 /* Assemble the array class name */
609 namelen = component->name->blength;
611 if (component->name->text[0] == '[') {
612 /* the component is itself an array */
613 namebuf = DMNEW(char, namelen + 1);
615 MCOPY(namebuf + 1, component->name->text, char, namelen);
619 /* the component is a non-array class */
620 namebuf = DMNEW(char, namelen + 3);
623 MCOPY(namebuf + 2, component->name->text, char, namelen);
624 namebuf[2 + namelen] = ';';
628 c = class_new(utf_new(namebuf, namelen));
630 /* load this class and link it */
642 /* class_multiarray_of *********************************************************
644 Returns an array class with the given dimension and element class.
645 The array class is dynamically created if neccessary.
647 *******************************************************************************/
649 classinfo *class_multiarray_of(s4 dim, classinfo *element)
655 panic("Invalid array dimension requested");
657 /* Assemble the array class name */
658 namelen = element->name->blength;
660 if (element->name->text[0] == '[') {
661 /* the element is itself an array */
662 namebuf = DMNEW(char, namelen + dim);
663 memcpy(namebuf + dim, element->name->text, namelen);
667 /* the element is a non-array class */
668 namebuf = DMNEW(char, namelen + 2 + dim);
670 memcpy(namebuf + dim + 1, element->name->text, namelen);
671 namelen += (2 + dim);
672 namebuf[namelen - 1] = ';';
674 memset(namebuf, '[', dim);
676 return class_new(utf_new(namebuf, namelen));
679 /* class_lookup_classref *******************************************************
681 Looks up the constant_classref for a given classname in the classref
685 cls..............the class containing the reference
686 name.............the name of the class refered to
689 a pointer to a constant_classref, or
690 NULL if the reference was not found
692 *******************************************************************************/
694 constant_classref *class_lookup_classref(classinfo *cls,utf *name)
696 constant_classref *ref;
697 extra_classref *xref;
702 CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
704 /* first search the main classref table */
705 count = cls->classrefcount;
706 ref = cls->classrefs;
707 for (; count; --count, ++ref)
708 if (ref->name == name)
711 /* next try the list of extra classrefs */
712 for (xref=cls->extclassrefs; xref; xref=xref->next) {
713 if (xref->classref.name == name)
714 return &(xref->classref);
722 /* class_get_classref **********************************************************
724 Returns the constant_classref for a given classname.
727 cls..............the class containing the reference
728 name.............the name of the class refered to
731 a pointer to a constant_classref (never NULL)
734 The given name is not checked for validity!
736 *******************************************************************************/
738 constant_classref *class_get_classref(classinfo *cls,utf *name)
740 constant_classref *ref;
741 extra_classref *xref;
746 ref = class_lookup_classref(cls,name);
750 xref = NEW(extra_classref);
751 CLASSREF_INIT(xref->classref,cls,name);
753 xref->next = cls->extclassrefs;
754 cls->extclassrefs = xref;
756 return &(xref->classref);
759 /* class_get_classref_multiarray_of ********************************************
761 Returns an array type reference with the given dimension and element class
765 dim..............the requested dimension
766 dim must be in [1;255]. This is NOT checked!
767 ref..............the component class reference
770 a pointer to the class reference for the array type
773 The referer of `ref` is used as the referer for the new classref.
775 *******************************************************************************/
777 constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref)
783 CLASS_ASSERT(dim >= 1 && dim <= 255);
785 /* Assemble the array class name */
786 namelen = ref->name->blength;
788 if (ref->name->text[0] == '[') {
789 /* the element is itself an array */
790 namebuf = DMNEW(char, namelen + dim);
791 memcpy(namebuf + dim, ref->name->text, namelen);
795 /* the element is a non-array class */
796 namebuf = DMNEW(char, namelen + 2 + dim);
798 memcpy(namebuf + dim + 1, ref->name->text, namelen);
799 namelen += (2 + dim);
800 namebuf[namelen - 1] = ';';
802 memset(namebuf, '[', dim);
804 return class_get_classref(ref->referer,utf_new(namebuf, namelen));
807 /* class_get_classref_component_of *********************************************
809 Returns the component classref of a given array type reference
812 ref..............the array type reference
815 a reference to the component class, or
816 NULL if `ref` is not an object array type reference
819 The referer of `ref` is used as the referer for the new classref.
821 *******************************************************************************/
823 constant_classref *class_get_classref_component_of(constant_classref *ref)
830 name = ref->name->text;
834 namelen = ref->name->blength - 1;
839 else if (*name != '[') {
843 return class_get_classref(ref->referer,utf_new(name, namelen));
848 * These are local overrides for various environment variables in Emacs.
849 * Please do not remove this and leave it at the end of the file, where
850 * Emacs will automagically detect them.
851 * ---------------------------------------------------------------------
854 * indent-tabs-mode: t