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 2181 2005-04-01 16:53:33Z edwin $
40 #include "vm/global.h"
41 #include "mm/memory.h"
43 #if defined(USE_THREADS)
44 # if defined(NATIVE_THREADS)
45 # include "threads/native/threads.h"
47 # include "threads/green/threads.h"
48 # include "threads/green/locks.h"
52 #include "toolbox/logging.h"
54 #include "vm/options.h"
55 #include "vm/resolve.h"
56 #include "vm/statistics.h"
57 #include "vm/tables.h"
59 #include "vm/loader.h"
62 /******************************************************************************/
64 /******************************************************************************/
71 #define CLASS_ASSERT(cond) assert(cond)
73 #define CLASS_ASSERT(cond)
77 /* global variables ***********************************************************/
79 hashtable class_hash; /* hashtable for classes */
81 list unlinkedclasses; /* this is only used for eager class */
85 /* frequently used classes ****************************************************/
87 /* important system classes */
89 classinfo *class_java_lang_Object;
90 classinfo *class_java_lang_Class;
91 classinfo *class_java_lang_ClassLoader;
92 classinfo *class_java_lang_Cloneable;
93 classinfo *class_java_lang_SecurityManager;
94 classinfo *class_java_lang_String;
95 classinfo *class_java_lang_System;
96 classinfo *class_java_io_Serializable;
99 /* system exception classes required in cacao */
101 classinfo *class_java_lang_Throwable;
102 classinfo *class_java_lang_VMThrowable;
103 classinfo *class_java_lang_Exception;
104 classinfo *class_java_lang_Error;
105 classinfo *class_java_lang_OutOfMemoryError;
106 classinfo *class_java_lang_NoClassDefFoundError;
108 classinfo *class_java_lang_Void;
109 classinfo *class_java_lang_Boolean;
110 classinfo *class_java_lang_Byte;
111 classinfo *class_java_lang_Character;
112 classinfo *class_java_lang_Short;
113 classinfo *class_java_lang_Integer;
114 classinfo *class_java_lang_Long;
115 classinfo *class_java_lang_Float;
116 classinfo *class_java_lang_Double;
118 /* some classes which may be used more often */
120 classinfo *class_java_util_Vector;
123 /* pseudo classes for the typechecker */
125 classinfo *pseudo_class_Arraystub;
126 classinfo *pseudo_class_Null;
127 classinfo *pseudo_class_New;
130 /* class_init ******************************************************************
132 Initialize the class subsystem.
134 *******************************************************************************/
136 void class_init_foo(void)
138 class_java_lang_Object = class_new_intern(utf_java_lang_Object);
140 class_java_lang_Class = class_new(utf_java_lang_Class);
141 class_java_lang_ClassLoader = class_new(utf_java_lang_ClassLoader);
142 class_java_lang_Cloneable = class_new(utf_java_lang_Cloneable);
143 class_java_lang_SecurityManager = class_new(utf_java_lang_SecurityManager);
144 class_java_lang_String = class_new(utf_java_lang_String);
145 class_java_lang_System = class_new(utf_java_lang_System);
146 class_java_io_Serializable = class_new(utf_java_io_Serializable);
148 class_java_lang_Throwable = class_new(utf_java_lang_Throwable);
149 class_java_lang_VMThrowable = class_new(utf_java_lang_VMThrowable);
150 class_java_lang_Exception = class_new(utf_java_lang_Exception);
151 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_NoClassDefFoundError =
157 class_new(utf_java_lang_NoClassDefFoundError);
159 class_java_lang_Void = class_new(utf_java_lang_Void);
160 class_java_lang_Boolean = class_new(utf_java_lang_Boolean);
161 class_java_lang_Byte = class_new(utf_java_lang_Byte);
162 class_java_lang_Character = class_new(utf_java_lang_Character);
163 class_java_lang_Short = class_new(utf_java_lang_Short);
164 class_java_lang_Integer = class_new(utf_java_lang_Integer);
165 class_java_lang_Long = class_new(utf_java_lang_Long);
166 class_java_lang_Float = class_new(utf_java_lang_Float);
167 class_java_lang_Double = class_new(utf_java_lang_Double);
169 class_java_util_Vector = class_new(utf_java_util_Vector);
171 pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
172 pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
173 pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
177 /* class_new *******************************************************************
179 Searches for the class with the specified name in the classes
180 hashtable, if there is no such class a new classinfo structure is
181 created and inserted into the list of classes to be loaded.
183 *******************************************************************************/
185 classinfo *class_new(utf *classname)
189 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
193 c = class_new_intern(classname);
195 /* we support eager class loading and linking on demand */
201 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
204 if (!load_class_bootstrap(c)) {
205 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
212 /* link all referenced classes */
214 tc = list_first(&unlinkedclasses);
217 /* skip the current loaded/linked class */
219 if (!link_class(tc)) {
220 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
227 /* we need a tmp variable here, because list_remove sets prev and
229 tmp = list_next(&unlinkedclasses, tc);
230 list_remove(&unlinkedclasses, tc);
235 if (!link_class(c)) {
236 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
244 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
252 classinfo *class_new_intern(utf *classname)
254 classinfo *c; /* hashtable element */
255 u4 key; /* hashkey computed from classname */
256 u4 slot; /* slot in hashtable */
259 key = utf_hashkey(classname->text, classname->blength);
260 slot = key & (class_hash.size - 1);
261 c = class_hash.ptr[slot];
263 /* search external hash chain for the class */
265 if (c->name->blength == classname->blength) {
266 for (i = 0; i < classname->blength; i++)
267 if (classname->text[i] != c->name->text[i]) goto nomatch;
269 /* class found in hashtable */
274 c = c->hashlink; /* next element in external chain */
277 /* location in hashtable found, create new classinfo structure */
279 #if defined(STATISTICS)
281 count_class_infos += sizeof(classinfo);
285 char logtext[MAXLOGTEXT];
286 sprintf(logtext, "Creating class: ");
287 utf_sprint_classname(logtext + strlen(logtext), classname);
291 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
292 /*c=NEW(classinfo);*/
296 c->packagename = NULL;
301 c->extclassrefs = NULL;
302 c->classrefcount = 0;
303 c->parseddescs = NULL;
304 c->parseddescsize = 0;
308 c->interfacescount = 0;
309 c->interfaces = NULL;
318 c->header.vftbl = NULL;
319 c->innerclasscount = 0;
320 c->innerclass = NULL;
322 c->initialized = false;
323 c->initializing = false;
324 c->classvftbl = false;
327 c->classloader = NULL;
328 c->sourcefile = NULL;
330 /* insert class into the hashtable */
331 c->hashlink = class_hash.ptr[slot];
332 class_hash.ptr[slot] = c;
334 /* update number of hashtable-entries */
335 class_hash.entries++;
337 if (class_hash.entries > (class_hash.size * 2)) {
339 /* reorganization of hashtable, average length of
340 the external chains is approx. 2 */
344 hashtable newhash; /* the new hashtable */
346 /* create new hashtable, double the size */
347 init_hashtable(&newhash, class_hash.size * 2);
348 newhash.entries = class_hash.entries;
350 /* transfer elements to new hashtable */
351 for (i = 0; i < class_hash.size; i++) {
352 c = (classinfo *) class_hash.ptr[i];
354 classinfo *nextc = c->hashlink;
355 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
357 c->hashlink = newhash.ptr[slot];
358 newhash.ptr[slot] = c;
364 /* dispose old table */
365 MFREE(class_hash.ptr, void*, class_hash.size);
366 class_hash = newhash;
369 /* Array classes need further initialization. */
370 if (c->name->text[0] == '[') {
371 /* Array classes are not loaded from classfiles. */
374 c->packagename = array_packagename;
377 /* Find the package name */
378 /* Classes in the unnamed package keep packagename == NULL. */
379 char *p = utf_end(c->name) - 1;
380 char *start = c->name->text;
381 for (;p > start; --p) {
383 c->packagename = utf_new (start, p - start);
389 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
390 initObjectLock(&c->header);
397 /* class_get *******************************************************************
399 Searches for the class with the specified name in the classes
400 hashtable if there is no such class NULL is returned.
402 *******************************************************************************/
404 classinfo *class_get(utf *classname)
406 classinfo *c; /* hashtable element */
407 u4 key; /* hashkey computed from classname */
408 u4 slot; /* slot in hashtable */
411 key = utf_hashkey(classname->text, classname->blength);
412 slot = key & (class_hash.size-1);
413 c = class_hash.ptr[slot];
415 /* search external hash-chain */
417 if (c->name->blength == classname->blength) {
418 /* compare classnames */
419 for (i = 0; i < classname->blength; i++)
420 if (classname->text[i] != c->name->text[i])
423 /* class found in hashtable */
431 /* class not found */
436 /* class_remove ****************************************************************
438 Removes the class entry wth the specified name in the classes
439 hashtable, furthermore the class' resources are freed if there is
440 no such class false is returned.
442 *******************************************************************************/
444 bool class_remove(classinfo *c)
446 classinfo *tc; /* hashtable element */
448 u4 key; /* hashkey computed from classname */
449 u4 slot; /* slot in hashtable */
452 key = utf_hashkey(c->name->text, c->name->blength);
453 slot = key & (class_hash.size - 1);
454 tc = class_hash.ptr[slot];
457 /* search external hash-chain */
459 if (tc->name->blength == c->name->blength) {
461 /* compare classnames */
462 for (i = 0; i < c->name->blength; i++)
463 if (tc->name->text[i] != c->name->text[i])
466 /* class found in hashtable */
468 class_hash.ptr[slot] = tc->hashlink;
470 pc->hashlink = tc->hashlink;
482 /* class not found */
487 /* class_freepool **************************************************************
489 Frees all resources used by this classes Constant Pool.
491 *******************************************************************************/
493 static void class_freecpool(classinfo *c)
499 if (c->cptags && c->cpinfos) {
500 for (idx = 0; idx < c->cpcount; idx++) {
501 tag = c->cptags[idx];
502 info = c->cpinfos[idx];
506 case CONSTANT_Fieldref:
507 case CONSTANT_Methodref:
508 case CONSTANT_InterfaceMethodref:
509 FREE(info, constant_FMIref);
511 case CONSTANT_Integer:
512 FREE(info, constant_integer);
515 FREE(info, constant_float);
518 FREE(info, constant_long);
520 case CONSTANT_Double:
521 FREE(info, constant_double);
523 case CONSTANT_NameAndType:
524 FREE(info, constant_nameandtype);
532 MFREE(c->cptags, u1, c->cpcount);
535 MFREE(c->cpinfos, voidptr, c->cpcount);
539 /* class_free ******************************************************************
541 Frees all resources used by the class.
543 *******************************************************************************/
545 void class_free(classinfo *c)
553 MFREE(c->interfaces, classinfo*, c->interfacescount);
556 for (i = 0; i < c->fieldscount; i++)
557 field_free(&(c->fields[i]));
558 /* MFREE(c->fields, fieldinfo, c->fieldscount); */
562 for (i = 0; i < c->methodscount; i++)
563 method_free(&(c->methods[i]));
564 MFREE(c->methods, methodinfo, c->methodscount);
567 if ((v = c->vftbl) != NULL) {
569 mem_free(v->arraydesc,sizeof(arraydescriptor));
571 for (i = 0; i < v->interfacetablelength; i++) {
572 MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
574 MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
576 i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
577 sizeof(methodptr*) * (v->interfacetablelength -
578 (v->interfacetablelength > 0));
579 v = (vftbl_t*) (((methodptr*) v) -
580 (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
585 MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
587 /* if (c->classvftbl)
588 mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
594 /* class_array_of **************************************************************
596 Returns an array class with the given component class. The array
597 class is dynamically created if neccessary.
599 *******************************************************************************/
601 classinfo *class_array_of(classinfo *component)
607 /* Assemble the array class name */
608 namelen = component->name->blength;
610 if (component->name->text[0] == '[') {
611 /* the component is itself an array */
612 namebuf = DMNEW(char, namelen + 1);
614 MCOPY(namebuf + 1, component->name->text, char, namelen);
618 /* the component is a non-array class */
619 namebuf = DMNEW(char, namelen + 3);
622 MCOPY(namebuf + 2, component->name->text, char, namelen);
623 namebuf[2 + namelen] = ';';
627 c = class_new(utf_new(namebuf, namelen));
629 /* load this class and link it */
641 /* class_multiarray_of *********************************************************
643 Returns an array class with the given dimension and element class.
644 The array class is dynamically created if neccessary.
646 *******************************************************************************/
648 classinfo *class_multiarray_of(s4 dim, classinfo *element)
654 panic("Invalid array dimension requested");
656 /* Assemble the array class name */
657 namelen = element->name->blength;
659 if (element->name->text[0] == '[') {
660 /* the element is itself an array */
661 namebuf = DMNEW(char, namelen + dim);
662 memcpy(namebuf + dim, element->name->text, namelen);
666 /* the element is a non-array class */
667 namebuf = DMNEW(char, namelen + 2 + dim);
669 memcpy(namebuf + dim + 1, element->name->text, namelen);
670 namelen += (2 + dim);
671 namebuf[namelen - 1] = ';';
673 memset(namebuf, '[', dim);
675 return class_new(utf_new(namebuf, namelen));
678 /* class_lookup_classref *******************************************************
680 Looks up the constant_classref for a given classname in the classref
684 cls..............the class containing the reference
685 name.............the name of the class refered to
688 a pointer to a constant_classref, or
689 NULL if the reference was not found
691 *******************************************************************************/
693 constant_classref *class_lookup_classref(classinfo *cls,utf *name)
695 constant_classref *ref;
696 extra_classref *xref;
701 CLASS_ASSERT(!cls->classrefcount || cls->classrefs);
703 /* first search the main classref table */
704 count = cls->classrefcount;
705 ref = cls->classrefs;
706 for (; count; --count, ++ref)
707 if (ref->name == name)
710 /* next try the list of extra classrefs */
711 for (xref=cls->extclassrefs; xref; xref=xref->next) {
712 if (xref->classref.name == name)
713 return &(xref->classref);
721 /* class_get_classref **********************************************************
723 Returns the constant_classref for a given classname.
726 cls..............the class containing the reference
727 name.............the name of the class refered to
730 a pointer to a constant_classref (never NULL)
733 The given name is not checked for validity!
735 *******************************************************************************/
737 constant_classref *class_get_classref(classinfo *cls,utf *name)
739 constant_classref *ref;
740 extra_classref *xref;
745 ref = class_lookup_classref(cls,name);
749 xref = NEW(extra_classref);
750 CLASSREF_INIT(xref->classref,cls,name);
752 xref->next = cls->extclassrefs;
753 cls->extclassrefs = xref;
755 return &(xref->classref);
758 /* class_get_classref_multiarray_of ********************************************
760 Returns an array type reference with the given dimension and element class
764 dim..............the requested dimension
765 dim must be in [1;255]. This is NOT checked!
766 ref..............the component class reference
769 a pointer to the class reference for the array type
772 The referer of `ref` is used as the referer for the new classref.
774 *******************************************************************************/
776 constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref)
782 CLASS_ASSERT(dim >= 1 && dim <= 255);
784 /* Assemble the array class name */
785 namelen = ref->name->blength;
787 if (ref->name->text[0] == '[') {
788 /* the element is itself an array */
789 namebuf = DMNEW(char, namelen + dim);
790 memcpy(namebuf + dim, ref->name->text, namelen);
794 /* the element is a non-array class */
795 namebuf = DMNEW(char, namelen + 2 + dim);
797 memcpy(namebuf + dim + 1, ref->name->text, namelen);
798 namelen += (2 + dim);
799 namebuf[namelen - 1] = ';';
801 memset(namebuf, '[', dim);
803 return class_get_classref(ref->referer,utf_new(namebuf, namelen));
806 /* class_get_classref_component_of *********************************************
808 Returns the component classref of a given array type reference
811 ref..............the array type reference
814 a reference to the component class, or
815 NULL if `ref` is not an object array type reference
818 The referer of `ref` is used as the referer for the new classref.
820 *******************************************************************************/
822 constant_classref *class_get_classref_component_of(constant_classref *ref)
829 name = ref->name->text;
833 namelen = ref->name->blength - 1;
838 else if (*name != '[') {
842 return class_get_classref(ref->referer,utf_new(name, namelen));
847 * These are local overrides for various environment variables in Emacs.
848 * Please do not remove this and leave it at the end of the file, where
849 * Emacs will automagically detect them.
850 * ---------------------------------------------------------------------
853 * indent-tabs-mode: t