1 /* src/vm/classcache.c - loaded class cache and loading constraints
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: Edwin Steiner
29 Changes: Christian Thalinger
31 $Id: classcache.c 3837 2005-12-01 23:50:28Z twisti $
41 #include "mm/memory.h"
42 #include "vm/classcache.h"
43 #include "vm/exceptions.h"
44 #include "vm/hashtable.h"
45 #include "vm/stringlocal.h"
49 /* initial number of slots in the classcache hash table */
50 #define CLASSCACHE_INIT_SIZE 2048
52 /*============================================================================*/
54 /*============================================================================*/
56 /*#define CLASSCACHE_VERBOSE*/
58 /*============================================================================*/
59 /* THREAD-SAFE LOCKING */
60 /*============================================================================*/
62 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
63 /* CAUTION: The static functions below are */
64 /* NOT synchronized! */
65 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
67 #if defined(USE_THREADS)
68 # define CLASSCACHE_LOCK() builtin_monitorenter(lock_hashtable_classcache)
69 # define CLASSCACHE_UNLOCK() builtin_monitorexit(lock_hashtable_classcache)
71 # define CLASSCACHE_LOCK()
72 # define CLASSCACHE_UNLOCK()
75 /*============================================================================*/
76 /* GLOBAL VARIABLES */
77 /*============================================================================*/
79 hashtable hashtable_classcache;
81 #if defined(USE_THREADS)
82 static java_objectheader *lock_hashtable_classcache;
86 /*============================================================================*/
88 /*============================================================================*/
90 /* classcache_init *************************************************************
92 Initialize the loaded class cache
94 Note: NOT synchronized!
96 *******************************************************************************/
98 bool classcache_init(void)
100 /* create the hashtable */
102 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
104 #if defined(USE_THREADS)
105 /* create utf hashtable lock object */
107 lock_hashtable_classcache = NEW(java_objectheader);
109 # if defined(NATIVE_THREADS)
110 initObjectLock(lock_hashtable_classcache);
114 /* everything's ok */
119 /* classcache_new_loader_entry *************************************************
121 Create a new classcache_loader_entry struct
122 (internally used helper function)
125 loader...........the ClassLoader object
126 next.............the next classcache_loader_entry
129 the new classcache_loader_entry
131 *******************************************************************************/
133 static classcache_loader_entry * classcache_new_loader_entry(
134 classloader * loader,
135 classcache_loader_entry * next)
137 classcache_loader_entry *lden;
139 lden = NEW(classcache_loader_entry);
140 lden->loader = loader;
146 /* classcache_merge_loaders ****************************************************
148 Merge two lists of loaders into one
149 (internally used helper function)
152 lista............first list (may be NULL)
153 listb............second list (may be NULL)
156 the merged list (may be NULL)
159 The lists given as arguments are destroyed!
161 *******************************************************************************/
163 static classcache_loader_entry * classcache_merge_loaders(
164 classcache_loader_entry * lista,
165 classcache_loader_entry * listb)
167 classcache_loader_entry *result;
168 classcache_loader_entry *ldenA;
169 classcache_loader_entry *ldenB;
170 classcache_loader_entry **chain;
172 /* XXX This is a quadratic algorithm. If this ever
173 * becomes a problem, the loader lists should be
174 * stored as sorted lists and merged in linear time. */
179 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
181 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
182 if (ldenB->loader == ldenA->loader)
186 /* this loader is only in lista */
188 chain = &(ldenA->next);
191 /* XXX free the duplicated element */
195 /* concat listb to the result */
202 /* classcache_lookup_name ******************************************************
204 Lookup a name in the first level of the cache
205 (internally used helper function)
208 name.............the name to look up
211 a pointer to the classcache_name_entry for this name, or
212 null if no entry was found.
214 *******************************************************************************/
216 static classcache_name_entry *classcache_lookup_name(utf *name)
218 classcache_name_entry *c; /* hash table element */
219 u4 key; /* hashkey computed from classname */
220 u4 slot; /* slot in hashtable */
223 key = utf_hashkey(name->text, (u4) name->blength);
224 slot = key & (hashtable_classcache.size - 1);
225 c = hashtable_classcache.ptr[slot];
227 /* search external hash chain for the entry */
230 /* entry found in hashtable */
235 c = c->hashlink; /* next element in external chain */
244 /* classcache_new_name *********************************************************
246 Return a classcache_name_entry for the given name. The entry is created
247 if it is not already in the cache.
248 (internally used helper function)
251 name.............the name to look up / create an entry for
254 a pointer to the classcache_name_entry for this name
256 *******************************************************************************/
258 static classcache_name_entry *classcache_new_name(utf *name)
260 classcache_name_entry *c; /* hash table element */
261 u4 key; /* hashkey computed from classname */
262 u4 slot; /* slot in hashtable */
265 key = utf_hashkey(name->text, (u4) name->blength);
266 slot = key & (hashtable_classcache.size - 1);
267 c = hashtable_classcache.ptr[slot];
269 /* search external hash chain for the entry */
272 /* entry found in hashtable */
277 c = c->hashlink; /* next element in external chain */
280 /* location in hashtable found, create new entry */
282 c = NEW(classcache_name_entry);
287 /* insert entry into hashtable */
288 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
289 hashtable_classcache.ptr[slot] = c;
291 /* update number of hashtable-entries */
292 hashtable_classcache.entries++;
294 if (hashtable_classcache.entries > (hashtable_classcache.size * 2)) {
296 /* reorganization of hashtable, average length of
297 the external chains is approx. 2 */
299 classcache_name_entry *c2;
300 hashtable newhash; /* the new hashtable */
302 /* create new hashtable, double the size */
304 hashtable_create(&newhash, hashtable_classcache.size * 2);
305 newhash.entries = hashtable_classcache.entries;
307 /* transfer elements to new hashtable */
309 for (i = 0; i < hashtable_classcache.size; i++) {
310 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
312 classcache_name_entry *nextc = c2->hashlink;
314 (utf_hashkey(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
316 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
317 newhash.ptr[newslot] = c2;
323 /* dispose old table */
325 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
326 hashtable_classcache = newhash;
333 /* classcache_lookup ***********************************************************
335 Lookup a possibly loaded class
338 initloader.......initiating loader for resolving the class name
339 classname........class name to look up
342 The return value is a pointer to the cached class object,
343 or NULL, if the class is not in the cache.
345 Note: synchronized with global tablelock
347 *******************************************************************************/
349 classinfo *classcache_lookup(classloader *initloader, utf *classname)
351 classcache_name_entry *en;
352 classcache_class_entry *clsen;
353 classcache_loader_entry *lden;
354 classinfo *cls = NULL;
358 en = classcache_lookup_name(classname);
361 /* iterate over all class entries */
363 for (clsen = en->classes; clsen; clsen = clsen->next) {
364 /* check if this entry has been loaded by initloader */
366 for (lden = clsen->loaders; lden; lden = lden->next) {
367 if (lden->loader == initloader) {
368 /* found the loaded class entry */
370 assert(clsen->classobj);
371 cls = clsen->classobj;
384 /* classcache_lookup_defined ***************************************************
386 Lookup a class with the given name and defining loader
389 defloader........defining loader
390 classname........class name
393 The return value is a pointer to the cached class object,
394 or NULL, if the class is not in the cache.
396 *******************************************************************************/
398 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
400 classcache_name_entry *en;
401 classcache_class_entry *clsen;
402 classinfo *cls = NULL;
406 en = classcache_lookup_name(classname);
409 /* iterate over all class entries */
410 for (clsen = en->classes; clsen; clsen = clsen->next) {
411 if (!clsen->classobj)
414 /* check if this entry has been defined by defloader */
415 if (clsen->classobj->classloader == defloader) {
416 cls = clsen->classobj;
428 /* classcache_lookup_defined_or_initiated **************************************
430 Lookup a class that has been defined or initiated by the given loader
433 loader...........defining or initiating loader
434 classname........class name to look up
437 The return value is a pointer to the cached class object,
438 or NULL, if the class is not in the cache.
440 Note: synchronized with global tablelock
442 *******************************************************************************/
444 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
447 classcache_name_entry *en;
448 classcache_class_entry *clsen;
449 classcache_loader_entry *lden;
450 classinfo *cls = NULL;
454 en = classcache_lookup_name(classname);
457 /* iterate over all class entries */
459 for (clsen = en->classes; clsen; clsen = clsen->next) {
461 /* check if this entry has been defined by loader */
462 if (clsen->classobj && clsen->classobj->classloader == loader) {
463 cls = clsen->classobj;
467 /* check if this entry has been initiated by loader */
468 for (lden = clsen->loaders; lden; lden = lden->next) {
469 if (lden->loader == loader) {
470 /* found the loaded class entry */
472 assert(clsen->classobj);
473 cls = clsen->classobj;
486 /* classcache_store ************************************************************
488 Store a loaded class. If a class of the same name has already been stored
489 with the same initiating loader, then the given class CLS is freed (if
490 possible) and the previously stored class is returned.
493 initloader.......initiating loader used to load the class
494 (may be NULL indicating the bootstrap loader)
495 cls..............class object to cache
496 mayfree..........true if CLS may be freed in case another class is
500 cls..............everything ok, the class was stored in the cache,
501 other classinfo..another class with the same (initloader,name) has been
502 stored earlier. CLS has been freed and the earlier
503 stored class is returned.
504 NULL.............an exception has been thrown.
506 Note: synchronized with global tablelock
508 *******************************************************************************/
510 classinfo * classcache_store(classloader * initloader,
514 classcache_name_entry *en;
515 classcache_class_entry *clsen;
516 classcache_loader_entry *lden;
517 #ifdef CLASSCACHE_VERBOSE
518 char logbuffer[1024];
522 assert(cls->loaded != 0);
526 #ifdef CLASSCACHE_VERBOSE
527 sprintf(logbuffer,"classcache_store (%p,%d,", (void*)initloader,mayfree);
528 utf_strcat(logbuffer, cls->name);
529 strcat(logbuffer,")");
533 en = classcache_new_name(cls->name);
537 /* iterate over all class entries */
538 for (clsen = en->classes; clsen; clsen = clsen->next) {
540 /* check if this entry has already been loaded by initloader */
541 for (lden = clsen->loaders; lden; lden = lden->next) {
542 if (lden->loader == initloader && clsen->classobj != cls) {
543 /* A class with the same (initloader,name) pair has been stored already. */
544 /* We free the given class and return the earlier one. */
545 #ifdef CLASSCACHE_VERBOSE
546 dolog("replacing %p with earlier loaded class %p",cls,clsen->classobj);
548 assert(clsen->classobj);
551 cls = clsen->classobj;
556 /* check if initloader is constrained to this entry */
557 for (lden = clsen->constraints; lden; lden = lden->next) {
558 if (lden->loader == initloader) {
559 /* we have to use this entry */
560 /* check if is has already been resolved to another class */
561 if (clsen->classobj && clsen->classobj != cls) {
562 /* a loading constraint is violated */
563 *exceptionptr = exceptions_new_linkageerror(
564 "loading constraint violated: ",cls);
565 goto return_exception;
568 /* record initloader as initiating loader */
569 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
571 /* record the loaded class object */
572 clsen->classobj = cls;
581 /* create a new class entry for this class object with */
582 /* initiating loader initloader */
584 clsen = NEW(classcache_class_entry);
585 clsen->classobj = cls;
586 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
587 clsen->constraints = NULL;
589 clsen->next = en->classes;
598 return NULL; /* exception */
601 /* classcache_store_unique *****************************************************
603 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
604 aroung classcache_store that throws an exception if a class with the same
605 name has already been loaded by the bootstrap loader.
607 This function is used to register a few special classes during startup.
608 It should not be used otherwise.
611 cls..............class object to cache
614 true.............everything ok, the class was stored.
615 false............an exception has been thrown.
617 Note: synchronized with global tablelock
619 *******************************************************************************/
621 bool classcache_store_unique(classinfo *cls)
625 result = classcache_store(NULL,cls,false);
630 *exceptionptr = new_internalerror("class already stored in the class cache");
637 /* classcache_store_defined ****************************************************
639 Store a loaded class after it has been defined. If the class has already
640 been defined by the same defining loader in another thread, free the given
641 class and returned the one which has been defined earlier.
644 cls..............class object to store. classloader must be set
645 (classloader may be NULL, for bootloader)
648 cls..............everything ok, the class was stored the cache,
649 other classinfo..the class had already been defined, CLS was freed, the
650 class which was defined earlier is returned,
651 NULL.............an exception has been thrown.
653 *******************************************************************************/
655 classinfo * classcache_store_defined(classinfo *cls)
657 classcache_name_entry *en;
658 classcache_class_entry *clsen;
659 #ifdef CLASSCACHE_VERBOSE
660 char logbuffer[1024];
664 assert(cls->loaded != 0);
668 #ifdef CLASSCACHE_VERBOSE
669 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
670 utf_strcat(logbuffer, cls->name);
671 strcat(logbuffer,")");
675 en = classcache_new_name(cls->name);
679 /* iterate over all class entries */
680 for (clsen = en->classes; clsen; clsen = clsen->next) {
682 /* check if this class has been defined by the same classloader */
683 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
684 /* we found an earlier definition, delete the newer one */
685 /* (if it is a different classinfo) */
686 if (clsen->classobj != cls) {
687 #ifdef CLASSCACHE_VERBOSE
688 dolog("replacing %p with earlier defined class %p",cls,clsen->classobj);
691 cls = clsen->classobj;
697 /* create a new class entry for this class object */
698 /* the list of initiating loaders is empty at this point */
700 clsen = NEW(classcache_class_entry);
701 clsen->classobj = cls;
702 clsen->loaders = NULL;
703 clsen->constraints = NULL;
705 clsen->next = en->classes;
713 /* classcache_find_loader ******************************************************
715 Find the class entry loaded by or constrained to a given loader
716 (internally used helper function)
719 entry............the classcache_name_entry
720 loader...........the loader to look for
723 the classcache_class_entry for the given loader, or
724 NULL if no entry was found
726 *******************************************************************************/
728 static classcache_class_entry * classcache_find_loader(
729 classcache_name_entry * entry,
730 classloader * loader)
732 classcache_class_entry *clsen;
733 classcache_loader_entry *lden;
737 /* iterate over all class entries */
738 for (clsen = entry->classes; clsen; clsen = clsen->next) {
740 /* check if this entry has already been loaded by initloader */
741 for (lden = clsen->loaders; lden; lden = lden->next) {
742 if (lden->loader == loader)
743 return clsen; /* found */
746 /* check if loader is constrained to this entry */
747 for (lden = clsen->constraints; lden; lden = lden->next) {
748 if (lden->loader == loader)
749 return clsen; /* found */
757 /* classcache_free_class_entry *************************************************
759 Free the memory used by a class entry
762 clsen............the classcache_class_entry to free
764 *******************************************************************************/
766 static void classcache_free_class_entry(classcache_class_entry * clsen)
768 classcache_loader_entry *lden;
769 classcache_loader_entry *next;
773 for (lden = clsen->loaders; lden; lden = next) {
775 FREE(lden, classcache_loader_entry);
777 for (lden = clsen->constraints; lden; lden = next) {
779 FREE(lden, classcache_loader_entry);
782 FREE(clsen, classcache_class_entry);
785 /* classcache_remove_class_entry ***********************************************
787 Remove a classcache_class_entry from the list of possible resolution of
789 (internally used helper function)
792 entry............the classcache_name_entry
793 clsen............the classcache_class_entry to remove
795 *******************************************************************************/
797 static void classcache_remove_class_entry(classcache_name_entry * entry,
798 classcache_class_entry * clsen)
800 classcache_class_entry **chain;
805 chain = &(entry->classes);
807 if (*chain == clsen) {
808 *chain = clsen->next;
809 classcache_free_class_entry(clsen);
812 chain = &((*chain)->next);
816 /* classcache_free_name_entry **************************************************
818 Free the memory used by a name entry
821 entry............the classcache_name_entry to free
823 *******************************************************************************/
825 static void classcache_free_name_entry(classcache_name_entry * entry)
827 classcache_class_entry *clsen;
828 classcache_class_entry *next;
832 for (clsen = entry->classes; clsen; clsen = next) {
834 classcache_free_class_entry(clsen);
837 FREE(entry, classcache_name_entry);
840 /* classcache_free *************************************************************
842 Free the memory used by the class cache
845 The class cache may not be used any more after this call, except
846 when it is reinitialized with classcache_init.
848 Note: NOT synchronized!
850 *******************************************************************************/
852 void classcache_free(void)
855 classcache_name_entry *entry;
856 classcache_name_entry *next;
858 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
859 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
860 next = entry->hashlink;
861 classcache_free_name_entry(entry);
865 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
866 hashtable_classcache.size = 0;
867 hashtable_classcache.entries = 0;
868 hashtable_classcache.ptr = NULL;
871 /* classcache_add_constraint ***************************************************
873 Add a loading constraint
876 a................first initiating loader
877 b................second initiating loader
878 classname........class name
881 true.............everything ok, the constraint has been added,
882 false............an exception has been thrown.
884 Note: synchronized with global tablelock
886 *******************************************************************************/
888 bool classcache_add_constraint(classloader * a,
892 classcache_name_entry *en;
893 classcache_class_entry *clsenA;
894 classcache_class_entry *clsenB;
898 #ifdef CLASSCACHE_VERBOSE
899 fprintf(stderr, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
900 utf_fprint_classname(stderr, classname);
901 fprintf(stderr, ")\n");
904 /* a constraint with a == b is trivially satisfied */
910 en = classcache_new_name(classname);
914 /* find the entry loaded by / constrained to each loader */
915 clsenA = classcache_find_loader(en, a);
916 clsenB = classcache_find_loader(en, b);
918 if (clsenA && clsenB) {
919 /* { both loaders have corresponding entries } */
921 /* if the entries are the same, the constraint is already recorded */
922 if (clsenA == clsenB)
925 /* check if the entries can be merged */
926 if (clsenA->classobj && clsenB->classobj
927 && clsenA->classobj != clsenB->classobj) {
928 /* no, the constraint is violated */
929 *exceptionptr = exceptions_new_linkageerror(
930 "loading constraint violated: ",clsenA->classobj);
931 goto return_exception;
934 /* yes, merge the entries */
935 /* clsenB will be merged into clsenA */
936 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
937 clsenB->loaders = NULL;
939 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
940 clsenB->constraints);
941 clsenB->constraints = NULL;
943 if (!clsenA->classobj)
944 clsenA->classobj = clsenB->classobj;
946 /* remove clsenB from the list of class entries */
947 classcache_remove_class_entry(en, clsenB);
950 /* { at most one of the loaders has a corresponding entry } */
952 /* set clsenA to the single class entry we have */
957 /* { no loader has a corresponding entry } */
959 /* create a new class entry with the constraint (a,b,en->name) */
960 clsenA = NEW(classcache_class_entry);
961 clsenA->classobj = NULL;
962 clsenA->loaders = NULL;
963 clsenA->constraints = classcache_new_loader_entry(b, NULL);
964 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
966 clsenA->next = en->classes;
967 en->classes = clsenA;
970 /* make b the loader that has no corresponding entry */
974 /* loader b must be added to entry clsenA */
975 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
985 return false; /* exception */
988 /*============================================================================*/
990 /*============================================================================*/
992 /* classcache_debug_dump *******************************************************
994 Print the contents of the loaded class cache to a stream
997 file.............output stream
999 Note: synchronized with global tablelock
1001 *******************************************************************************/
1004 void classcache_debug_dump(FILE * file)
1006 classcache_name_entry *c;
1007 classcache_class_entry *clsen;
1008 classcache_loader_entry *lden;
1013 fprintf(file, "\n=== [loaded class cache] =====================================\n\n");
1014 fprintf(file, "hash size : %d\n", (int) hashtable_classcache.size);
1015 fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries);
1016 fprintf(file, "\n");
1018 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1019 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1021 for (; c; c = c->hashlink) {
1022 utf_fprint_classname(file, c->name);
1023 fprintf(file, "\n");
1025 /* iterate over all class entries */
1026 for (clsen = c->classes; clsen; clsen = clsen->next) {
1027 if (clsen->classobj) {
1028 fprintf(file, " loaded %p\n", (void *) clsen->classobj);
1031 fprintf(file, " unresolved\n");
1033 fprintf(file, " loaders:");
1034 for (lden = clsen->loaders; lden; lden = lden->next) {
1035 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1037 fprintf(file, "\n constraints:");
1038 for (lden = clsen->constraints; lden; lden = lden->next) {
1039 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1041 fprintf(file, "\n");
1045 fprintf(file, "\n==============================================================\n\n");
1047 CLASSCACHE_UNLOCK();
1052 * These are local overrides for various environment variables in Emacs.
1053 * Please do not remove this and leave it at the end of the file, where
1054 * Emacs will automagically detect them.
1055 * ---------------------------------------------------------------------
1058 * indent-tabs-mode: t
1062 * vim:noexpandtab:sw=4:ts=4: