1 /* 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 2078 2005-03-25 13:30:14Z edwin $
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/loader.h"
57 #include "vm/options.h"
58 #include "vm/statistics.h"
59 #include "vm/tables.h"
63 /* global variables ***********************************************************/
65 hashtable class_hash; /* hashtable for classes */
67 list unlinkedclasses; /* this is only used for eager class */
71 /* frequently used classes ****************************************************/
73 /* important system classes */
75 classinfo *class_java_lang_Object;
76 classinfo *class_java_lang_Class;
77 classinfo *class_java_lang_ClassLoader;
78 classinfo *class_java_lang_Cloneable;
79 classinfo *class_java_lang_SecurityManager;
80 classinfo *class_java_lang_String;
81 classinfo *class_java_lang_System;
82 classinfo *class_java_io_Serializable;
85 /* system exception classes required in cacao */
87 classinfo *class_java_lang_Throwable;
88 classinfo *class_java_lang_VMThrowable;
89 classinfo *class_java_lang_Exception;
90 classinfo *class_java_lang_Error;
91 classinfo *class_java_lang_OutOfMemoryError;
94 classinfo *class_java_lang_Void;
95 classinfo *class_java_lang_Boolean;
96 classinfo *class_java_lang_Byte;
97 classinfo *class_java_lang_Character;
98 classinfo *class_java_lang_Short;
99 classinfo *class_java_lang_Integer;
100 classinfo *class_java_lang_Long;
101 classinfo *class_java_lang_Float;
102 classinfo *class_java_lang_Double;
104 /* some classes which may be used more often */
106 classinfo *class_java_util_Vector;
109 /* pseudo classes for the typechecker */
111 classinfo *pseudo_class_Arraystub;
112 classinfo *pseudo_class_Null;
113 classinfo *pseudo_class_New;
116 /* class_init ******************************************************************
118 Initialize the class subsystem.
120 *******************************************************************************/
122 void class_init_foo(void)
124 class_java_lang_Object = class_new_intern(utf_java_lang_Object);
126 class_java_lang_Class = class_new(utf_java_lang_Class);
127 class_java_lang_ClassLoader = class_new(utf_java_lang_ClassLoader);
128 class_java_lang_Cloneable = class_new(utf_java_lang_Cloneable);
129 class_java_lang_SecurityManager = class_new(utf_java_lang_SecurityManager);
130 class_java_lang_String = class_new(utf_java_lang_String);
131 class_java_lang_System = class_new(utf_java_lang_System);
132 class_java_io_Serializable = class_new(utf_java_io_Serializable);
134 class_java_lang_Throwable = class_new(utf_java_lang_Throwable);
135 class_java_lang_VMThrowable = class_new(utf_java_lang_VMThrowable);
136 class_java_lang_Exception = class_new(utf_java_lang_Exception);
137 class_java_lang_Error = class_new(utf_java_lang_Error);
138 class_java_lang_OutOfMemoryError =
139 class_new(utf_java_lang_OutOfMemoryError);
141 class_java_lang_Void = class_new(utf_java_lang_Void);
142 class_java_lang_Boolean = class_new(utf_java_lang_Boolean);
143 class_java_lang_Byte = class_new(utf_java_lang_Byte);
144 class_java_lang_Character = class_new(utf_java_lang_Character);
145 class_java_lang_Short = class_new(utf_java_lang_Short);
146 class_java_lang_Integer = class_new(utf_java_lang_Integer);
147 class_java_lang_Long = class_new(utf_java_lang_Long);
148 class_java_lang_Float = class_new(utf_java_lang_Float);
149 class_java_lang_Double = class_new(utf_java_lang_Double);
151 class_java_util_Vector = class_new(utf_java_util_Vector);
153 pseudo_class_Arraystub = class_new_intern(utf_new_char("$ARRAYSTUB$"));
154 pseudo_class_Null = class_new_intern(utf_new_char("$NULL$"));
155 pseudo_class_New = class_new_intern(utf_new_char("$NEW$"));
159 /* class_new *******************************************************************
161 Searches for the class with the specified name in the classes
162 hashtable, if there is no such class a new classinfo structure is
163 created and inserted into the list of classes to be loaded.
165 *******************************************************************************/
167 classinfo *class_new(utf *classname)
171 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
175 c = class_new_intern(classname);
177 /* we support eager class loading and linking on demand */
183 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
186 if (!class_load(c)) {
187 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
194 /* link all referenced classes */
196 tc = list_first(&unlinkedclasses);
199 /* skip the current loaded/linked class */
201 if (!class_link(tc)) {
202 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
209 /* we need a tmp variable here, because list_remove sets prev and
211 tmp = list_next(&unlinkedclasses, tc);
212 list_remove(&unlinkedclasses, tc);
217 if (!class_link(c)) {
218 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
226 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
234 classinfo *class_new_intern(utf *classname)
236 classinfo *c; /* hashtable element */
237 u4 key; /* hashkey computed from classname */
238 u4 slot; /* slot in hashtable */
241 key = utf_hashkey(classname->text, classname->blength);
242 slot = key & (class_hash.size - 1);
243 c = class_hash.ptr[slot];
245 /* search external hash chain for the class */
247 if (c->name->blength == classname->blength) {
248 for (i = 0; i < classname->blength; i++)
249 if (classname->text[i] != c->name->text[i]) goto nomatch;
251 /* class found in hashtable */
256 c = c->hashlink; /* next element in external chain */
259 /* location in hashtable found, create new classinfo structure */
261 #if defined(STATISTICS)
263 count_class_infos += sizeof(classinfo);
267 char logtext[MAXLOGTEXT];
268 sprintf(logtext, "Creating class: ");
269 utf_sprint_classname(logtext + strlen(logtext), classname);
273 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
274 /*c=NEW(classinfo);*/
278 c->packagename = NULL;
283 c->classrefcount = 0;
284 c->parseddescs = NULL;
285 c->parseddescsize = 0;
289 c->interfacescount = 0;
290 c->interfaces = NULL;
299 c->header.vftbl = NULL;
300 c->innerclasscount = 0;
301 c->innerclass = NULL;
303 c->initialized = false;
304 c->initializing = false;
305 c->classvftbl = false;
308 c->classloader = NULL;
309 c->sourcefile = NULL;
311 /* insert class into the hashtable */
312 c->hashlink = class_hash.ptr[slot];
313 class_hash.ptr[slot] = c;
315 /* update number of hashtable-entries */
316 class_hash.entries++;
318 if (class_hash.entries > (class_hash.size * 2)) {
320 /* reorganization of hashtable, average length of
321 the external chains is approx. 2 */
325 hashtable newhash; /* the new hashtable */
327 /* create new hashtable, double the size */
328 init_hashtable(&newhash, class_hash.size * 2);
329 newhash.entries = class_hash.entries;
331 /* transfer elements to new hashtable */
332 for (i = 0; i < class_hash.size; i++) {
333 c = (classinfo *) class_hash.ptr[i];
335 classinfo *nextc = c->hashlink;
336 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
338 c->hashlink = newhash.ptr[slot];
339 newhash.ptr[slot] = c;
345 /* dispose old table */
346 MFREE(class_hash.ptr, void*, class_hash.size);
347 class_hash = newhash;
350 /* Array classes need further initialization. */
351 if (c->name->text[0] == '[') {
352 /* Array classes are not loaded from classfiles. */
355 c->packagename = array_packagename;
358 /* Find the package name */
359 /* Classes in the unnamed package keep packagename == NULL. */
360 char *p = utf_end(c->name) - 1;
361 char *start = c->name->text;
362 for (;p > start; --p) {
364 c->packagename = utf_new (start, p - start);
370 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
371 initObjectLock(&c->header);
378 /* class_get *******************************************************************
380 Searches for the class with the specified name in the classes
381 hashtable if there is no such class NULL is returned.
383 *******************************************************************************/
385 classinfo *class_get(utf *classname)
387 classinfo *c; /* hashtable element */
388 u4 key; /* hashkey computed from classname */
389 u4 slot; /* slot in hashtable */
392 key = utf_hashkey(classname->text, classname->blength);
393 slot = key & (class_hash.size-1);
394 c = class_hash.ptr[slot];
396 /* search external hash-chain */
398 if (c->name->blength == classname->blength) {
399 /* compare classnames */
400 for (i = 0; i < classname->blength; i++)
401 if (classname->text[i] != c->name->text[i])
404 /* class found in hashtable */
412 /* class not found */
417 /* class_remove ****************************************************************
419 Removes the class entry wth the specified name in the classes
420 hashtable, furthermore the class' resources are freed if there is
421 no such class false is returned.
423 *******************************************************************************/
425 bool class_remove(classinfo *c)
427 classinfo *tc; /* hashtable element */
429 u4 key; /* hashkey computed from classname */
430 u4 slot; /* slot in hashtable */
433 key = utf_hashkey(c->name->text, c->name->blength);
434 slot = key & (class_hash.size - 1);
435 tc = class_hash.ptr[slot];
438 /* search external hash-chain */
440 if (tc->name->blength == c->name->blength) {
442 /* compare classnames */
443 for (i = 0; i < c->name->blength; i++)
444 if (tc->name->text[i] != c->name->text[i])
447 /* class found in hashtable */
449 class_hash.ptr[slot] = tc->hashlink;
451 pc->hashlink = tc->hashlink;
463 /* class not found */
468 /* class_array_of **************************************************************
470 Returns an array class with the given component class. The array
471 class is dynamically created if neccessary.
473 *******************************************************************************/
475 classinfo *class_array_of(classinfo *component)
481 /* Assemble the array class name */
482 namelen = component->name->blength;
484 if (component->name->text[0] == '[') {
485 /* the component is itself an array */
486 namebuf = DMNEW(char, namelen + 1);
488 MCOPY(namebuf + 1, component->name->text, char, namelen);
492 /* the component is a non-array class */
493 namebuf = DMNEW(char, namelen + 3);
496 MCOPY(namebuf + 2, component->name->text, char, namelen);
497 namebuf[2 + namelen] = ';';
501 c = class_new(utf_new(namebuf, namelen));
503 /* load this class ;-) and link it */
516 /* class_multiarray_of *********************************************************
518 Returns an array class with the given dimension and element class.
519 The array class is dynamically created if neccessary.
521 *******************************************************************************/
523 classinfo *class_multiarray_of(s4 dim, classinfo *element)
529 panic("Invalid array dimension requested");
531 /* Assemble the array class name */
532 namelen = element->name->blength;
534 if (element->name->text[0] == '[') {
535 /* the element is itself an array */
536 namebuf = DMNEW(char, namelen + dim);
537 memcpy(namebuf + dim, element->name->text, namelen);
541 /* the element is a non-array class */
542 namebuf = DMNEW(char, namelen + 2 + dim);
544 memcpy(namebuf + dim + 1, element->name->text, namelen);
545 namelen += (2 + dim);
546 namebuf[namelen - 1] = ';';
548 memset(namebuf, '[', dim);
550 return class_new(utf_new(namebuf, namelen));
555 * These are local overrides for various environment variables in Emacs.
556 * Please do not remove this and leave it at the end of the file, where
557 * Emacs will automagically detect them.
558 * ---------------------------------------------------------------------
561 * indent-tabs-mode: t