1 /* src/vm/classcache.c - loaded class cache and loading constraints
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
29 Changes: Christian Thalinger
31 $Id: classcache.c 4690 2006-03-27 11:37:46Z twisti $
42 #include "mm/memory.h"
43 #include "vm/classcache.h"
44 #include "vm/exceptions.h"
45 #include "vm/hashtable.h"
46 #include "vm/stringlocal.h"
50 /*************************************************************************
54 The classcache has two functions:
56 1) caching the resolution of class references
57 2) storing and checking loading constraints
59 We will use the following terms in this description:
61 N a class name: a utf string
62 (N,L) a class reference with initiating loader L and class name N
63 C a class (object): the result of resolving a reference (N,L)
64 We will write resultion as
66 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
67 resolve to the same class C. So (N,L1,L2) means
70 The functions of the classcache require:
72 1) a mapping (N,L) |--> C for looking up prior resolution results.
73 2) storing the current set of loading constraints { (N,L1,L2) }
75 These functions can be rearranged like that:
77 a mapping N |--> (a mapping L |--> C or NULL,
78 a set of constraints {(L1,L2)})
80 Thus we can treat the mapping and constraints for each name N
81 separately. The implementation does this by keeping a hash table
82 mapping a name N to a `classcache_name_entry` which contains all
83 info with respect to N.
85 For a class name N we can define an equivalence relation ~N~ on
88 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
90 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
92 Also, if two references (N,L1) and (N,L2) resolve to the same class C
93 we have L1 ~N~ L2 because class loaders are required to return
94 consistent resolutions for a name N [XXX].
96 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
98 Cx...is a class C or NULL
99 IL...is the set of initiating loaders
100 CL...is the set of constrained loaders
102 Such a tuple is called `classcache_class_entry` in the source code.
104 The following holds for each tuple (Cx,IL,CL):
106 . (Cx is NULL) implies IL = {}.
108 . If Cx is a class, IL is the set of loaders that have been
109 recorded as initiating loaders for Cx. IL may be the
110 empty set {} in case Cx has already been defined but no
111 initiating loader has been recorded, yet.
113 . (IL u CL) is a subset of an equivalence class of ~N~.
115 (This means that all loaders in IL and CL must resolve
116 the name N to the same class.)
118 The following holds for the set of tuples { (Cx,IL,CL) }:
120 . For a given class C there is at most one tuple with Cx = C
121 in the set. (There may be an arbitrary number of tuples
122 with Cx = NULL, however.)
124 . For a given loader L there is at most one tuple with
127 The implementation stores sets of loaders as linked lists of
128 `classcache_loader_entry`s.
130 Comments about manipulating the classcache can be found in the
131 individual functions below.
133 *************************************************************************/
136 /* initial number of slots in the classcache hash table */
137 #define CLASSCACHE_INIT_SIZE 2048
139 /*============================================================================*/
141 /*============================================================================*/
143 /*#define CLASSCACHE_VERBOSE*/
145 /*============================================================================*/
147 /*============================================================================*/
149 /*#define CLASSCACHE_STATS*/
151 #ifdef CLASSCACHE_STATS
152 static int stat_classnames_stored = 0;
153 static int stat_classes_stored = 0;
154 static int stat_trivial_constraints = 0;
155 static int stat_nontriv_constraints = 0;
156 static int stat_nontriv_constraints_both = 0;
157 static int stat_nontriv_constraints_merged = 0;
158 static int stat_nontriv_constraints_one = 0;
159 static int stat_nontriv_constraints_none = 0;
160 static int stat_new_loader_entry = 0;
161 static int stat_merge_class_entries = 0;
162 static int stat_merge_loader_entries = 0;
163 static int stat_lookup = 0;
164 static int stat_lookup_class_entry_checked = 0;
165 static int stat_lookup_loader_checked = 0;
166 static int stat_lookup_name = 0;
167 static int stat_lookup_name_entry = 0;
168 static int stat_lookup_name_notfound = 0;
169 static int stat_lookup_new_name = 0;
170 static int stat_lookup_new_name_entry = 0;
171 static int stat_lookup_new_name_collisions = 0;
172 static int stat_rehash_names = 0;
173 static int stat_rehash_names_collisions = 0;
175 #define CLASSCACHE_COUNT(cnt) (cnt)++
176 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
178 void classcache_print_statistics(FILE *file) {
179 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
180 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
181 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
182 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
183 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
184 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
185 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
186 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
187 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
188 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
189 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
190 fprintf(file,"lookups : %8d\n",stat_lookup);
191 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
192 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
193 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
194 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
195 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
196 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
197 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
198 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
199 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
200 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
203 #define CLASSCACHE_COUNT(cnt)
204 #define CLASSCACHE_COUNTIF(cond,cnt)
207 /*============================================================================*/
208 /* THREAD-SAFE LOCKING */
209 /*============================================================================*/
211 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
212 /* CAUTION: The static functions below are */
213 /* NOT synchronized! */
214 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
216 #if defined(USE_THREADS)
217 # define CLASSCACHE_LOCK() builtin_monitorenter(lock_hashtable_classcache)
218 # define CLASSCACHE_UNLOCK() builtin_monitorexit(lock_hashtable_classcache)
220 # define CLASSCACHE_LOCK()
221 # define CLASSCACHE_UNLOCK()
224 /*============================================================================*/
225 /* GLOBAL VARIABLES */
226 /*============================================================================*/
228 hashtable hashtable_classcache;
230 #if defined(USE_THREADS)
231 static java_objectheader *lock_hashtable_classcache;
235 /*============================================================================*/
237 /*============================================================================*/
241 static void classcache_free_class_entry(classcache_class_entry *clsen);
242 static void classcache_remove_class_entry(classcache_name_entry *en,
243 classcache_class_entry *clsen);
245 /* hash function to use */
247 #define CLASSCACHE_HASH utf_full_hashkey
249 /* classcache_init *************************************************************
251 Initialize the class cache
253 Note: NOT synchronized!
255 *******************************************************************************/
257 bool classcache_init(void)
259 /* create the hashtable */
261 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
263 #if defined(USE_THREADS)
264 /* create utf hashtable lock object */
266 lock_hashtable_classcache = NEW(java_objectheader);
268 # if defined(NATIVE_THREADS)
269 initObjectLock(lock_hashtable_classcache);
273 /* everything's ok */
278 /* classcache_new_loader_entry *************************************************
280 Create a new classcache_loader_entry struct
281 (internally used helper function)
284 loader...........the ClassLoader object
285 next.............the next classcache_loader_entry
288 the new classcache_loader_entry
290 *******************************************************************************/
292 static classcache_loader_entry * classcache_new_loader_entry(
293 classloader * loader,
294 classcache_loader_entry * next)
296 classcache_loader_entry *lden;
298 lden = NEW(classcache_loader_entry);
299 lden->loader = loader;
301 CLASSCACHE_COUNT(stat_new_loader_entry);
306 /* classcache_merge_loaders ****************************************************
308 Merge two lists of loaders into one
309 (internally used helper function)
312 lista............first list (may be NULL)
313 listb............second list (may be NULL)
316 the merged list (may be NULL)
319 The lists given as arguments are destroyed!
321 *******************************************************************************/
323 static classcache_loader_entry * classcache_merge_loaders(
324 classcache_loader_entry * lista,
325 classcache_loader_entry * listb)
327 classcache_loader_entry *result;
328 classcache_loader_entry *ldenA;
329 classcache_loader_entry *ldenB;
330 classcache_loader_entry **chain;
332 CLASSCACHE_COUNT(stat_merge_loader_entries);
334 /* XXX This is a quadratic algorithm. If this ever
335 * becomes a problem, the loader lists should be
336 * stored as sorted lists and merged in linear time. */
341 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
343 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
344 if (ldenB->loader == ldenA->loader)
348 /* this loader is only in lista */
350 chain = &(ldenA->next);
353 /* XXX free the duplicated element */
357 /* concat listb to the result */
363 /* classcache_merge_class_entries **********************************************
365 Merge two `classcache_class_entry`s into one.
366 (internally used helper function)
369 en...............the classcache_name_entry containing both class entries
370 clsenA...........first class entry, will receive the result
371 clsenB...........second class entry
374 Either both entries must have the same classobj, or one of them has
378 clsenB is freed by this function!
380 *******************************************************************************/
382 static void classcache_merge_class_entries(classcache_name_entry *en,
383 classcache_class_entry *clsenA,
384 classcache_class_entry *clsenB)
386 #ifdef CLASSCACHE_VERBOSE
387 char logbuffer[1024];
393 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
395 #ifdef CLASSCACHE_VERBOSE
396 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
397 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
398 if (clsenA->classobj)
399 utf_strcat(logbuffer, clsenA->classobj->name);
400 if (clsenB->classobj)
401 utf_strcat(logbuffer, clsenB->classobj->name);
405 CLASSCACHE_COUNT(stat_merge_class_entries);
407 /* clsenB will be merged into clsenA */
408 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
409 clsenB->loaders = NULL; /* these have been freed or reused */
411 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
412 clsenB->constraints);
413 clsenB->constraints = NULL; /* these have been freed or reused */
415 if (!clsenA->classobj)
416 clsenA->classobj = clsenB->classobj;
418 /* remove clsenB from the list of class entries */
419 classcache_remove_class_entry(en, clsenB);
423 /* classcache_lookup_name ******************************************************
425 Lookup a name in the first level of the cache
426 (internally used helper function)
429 name.............the name to look up
432 a pointer to the classcache_name_entry for this name, or
433 null if no entry was found.
435 *******************************************************************************/
437 static classcache_name_entry *classcache_lookup_name(utf *name)
439 classcache_name_entry *c; /* hash table element */
440 u4 key; /* hashkey computed from classname */
441 u4 slot; /* slot in hashtable */
443 CLASSCACHE_COUNT(stat_lookup_name);
445 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
446 slot = key & (hashtable_classcache.size - 1);
447 c = hashtable_classcache.ptr[slot];
449 /* search external hash chain for the entry */
452 /* entry found in hashtable */
453 CLASSCACHE_COUNT(stat_lookup_name_entry);
458 c = c->hashlink; /* next element in external chain */
463 CLASSCACHE_COUNT(stat_lookup_name_notfound);
468 /* classcache_new_name *********************************************************
470 Return a classcache_name_entry for the given name. The entry is created
471 if it is not already in the cache.
472 (internally used helper function)
475 name.............the name to look up / create an entry for
478 a pointer to the classcache_name_entry for this name
480 *******************************************************************************/
482 static classcache_name_entry *classcache_new_name(utf *name)
484 classcache_name_entry *c; /* hash table element */
485 u4 key; /* hashkey computed from classname */
486 u4 slot; /* slot in hashtable */
489 CLASSCACHE_COUNT(stat_lookup_new_name);
491 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
492 slot = key & (hashtable_classcache.size - 1);
493 c = hashtable_classcache.ptr[slot];
495 /* search external hash chain for the entry */
498 /* entry found in hashtable */
499 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
504 c = c->hashlink; /* next element in external chain */
507 /* location in hashtable found, create new entry */
509 c = NEW(classcache_name_entry);
514 /* insert entry into hashtable */
515 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
516 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
517 hashtable_classcache.ptr[slot] = c;
519 /* update number of hashtable-entries */
520 hashtable_classcache.entries++;
521 CLASSCACHE_COUNT(stat_classnames_stored);
523 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
524 /* reorganization of hashtable */
526 classcache_name_entry *c2;
527 hashtable newhash; /* the new hashtable */
529 CLASSCACHE_COUNT(stat_rehash_names);
531 /* create new hashtable, double the size */
533 hashtable_create(&newhash, hashtable_classcache.size * 2);
534 newhash.entries = hashtable_classcache.entries;
536 /* transfer elements to new hashtable */
538 for (i = 0; i < hashtable_classcache.size; i++) {
539 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
541 classcache_name_entry *nextc = c2->hashlink;
543 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
545 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
546 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
547 newhash.ptr[newslot] = c2;
553 /* dispose old table */
555 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
556 hashtable_classcache = newhash;
563 /* classcache_lookup ***********************************************************
565 Lookup a possibly loaded class
568 initloader.......initiating loader for resolving the class name
569 classname........class name to look up
572 The return value is a pointer to the cached class object,
573 or NULL, if the class is not in the cache.
575 Note: synchronized with global tablelock
577 *******************************************************************************/
579 classinfo *classcache_lookup(classloader *initloader, utf *classname)
581 classcache_name_entry *en;
582 classcache_class_entry *clsen;
583 classcache_loader_entry *lden;
584 classinfo *cls = NULL;
588 CLASSCACHE_COUNT(stat_lookup);
589 en = classcache_lookup_name(classname);
592 /* iterate over all class entries */
594 for (clsen = en->classes; clsen; clsen = clsen->next) {
595 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
596 /* check if this entry has been loaded by initloader */
598 for (lden = clsen->loaders; lden; lden = lden->next) {
599 CLASSCACHE_COUNT(stat_lookup_loader_checked);
600 if (lden->loader == initloader) {
601 /* found the loaded class entry */
603 assert(clsen->classobj);
604 cls = clsen->classobj;
617 /* classcache_lookup_defined ***************************************************
619 Lookup a class with the given name and defining loader
622 defloader........defining loader
623 classname........class name
626 The return value is a pointer to the cached class object,
627 or NULL, if the class is not in the cache.
629 *******************************************************************************/
631 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
633 classcache_name_entry *en;
634 classcache_class_entry *clsen;
635 classinfo *cls = NULL;
639 en = classcache_lookup_name(classname);
642 /* iterate over all class entries */
643 for (clsen = en->classes; clsen; clsen = clsen->next) {
644 if (!clsen->classobj)
647 /* check if this entry has been defined by defloader */
648 if (clsen->classobj->classloader == defloader) {
649 cls = clsen->classobj;
661 /* classcache_lookup_defined_or_initiated **************************************
663 Lookup a class that has been defined or initiated by the given loader
666 loader...........defining or initiating loader
667 classname........class name to look up
670 The return value is a pointer to the cached class object,
671 or NULL, if the class is not in the cache.
673 Note: synchronized with global tablelock
675 *******************************************************************************/
677 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
680 classcache_name_entry *en;
681 classcache_class_entry *clsen;
682 classcache_loader_entry *lden;
683 classinfo *cls = NULL;
687 en = classcache_lookup_name(classname);
690 /* iterate over all class entries */
692 for (clsen = en->classes; clsen; clsen = clsen->next) {
694 /* check if this entry has been defined by loader */
695 if (clsen->classobj && clsen->classobj->classloader == loader) {
696 cls = clsen->classobj;
700 /* check if this entry has been initiated by loader */
701 for (lden = clsen->loaders; lden; lden = lden->next) {
702 if (lden->loader == loader) {
703 /* found the loaded class entry */
705 assert(clsen->classobj);
706 cls = clsen->classobj;
719 /* classcache_store ************************************************************
721 Store a loaded class. If a class of the same name has already been stored
722 with the same initiating loader, then the given class CLS is freed (if
723 possible) and the previously stored class is returned.
726 initloader.......initiating loader used to load the class
727 (may be NULL indicating the bootstrap loader)
728 cls..............class object to cache
729 mayfree..........true if CLS may be freed in case another class is
733 cls..............everything ok, the class was stored in the cache,
734 other classinfo..another class with the same (initloader,name) has been
735 stored earlier. CLS has been freed[1] and the earlier
736 stored class is returned.
737 NULL.............an exception has been thrown.
739 Note: synchronized with global tablelock
741 [1]...in case MAYFREE is true
743 *******************************************************************************/
745 classinfo *classcache_store(classloader *initloader, classinfo *cls,
748 classcache_name_entry *en;
749 classcache_class_entry *clsen;
750 classcache_class_entry *clsenB;
751 classcache_loader_entry *lden;
752 #ifdef CLASSCACHE_VERBOSE
753 char logbuffer[1024];
757 assert(cls->state & CLASS_LOADED);
761 #ifdef CLASSCACHE_VERBOSE
762 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
763 utf_strcat(logbuffer, cls->name);
764 strcat(logbuffer,")");
768 en = classcache_new_name(cls->name);
772 /* iterate over all class entries */
773 for (clsen = en->classes; clsen; clsen = clsen->next) {
775 /* check if this entry has already been loaded by initloader */
776 for (lden = clsen->loaders; lden; lden = lden->next) {
777 if (lden->loader == initloader) {
778 if (clsen->classobj != cls) {
779 /* A class with the same (initloader,name) pair has been stored already. */
780 /* We free the given class and return the earlier one. */
781 #ifdef CLASSCACHE_VERBOSE
782 dolog("replacing %p with earlier loaded class %p",cls,clsen->classobj);
784 assert(clsen->classobj);
787 cls = clsen->classobj;
793 /* {This entry has not been resolved with initloader} */
795 /* check if initloader is constrained to this entry */
796 for (lden = clsen->constraints; lden; lden = lden->next) {
797 if (lden->loader == initloader) {
798 /* we have to use this entry. check if it has been resolved */
799 if (clsen->classobj) {
800 /* check if is has already been resolved to another class */
801 if (clsen->classobj != cls) {
802 /* a loading constraint is violated */
803 *exceptionptr = exceptions_new_linkageerror(
804 "loading constraint violated: ",cls);
805 goto return_exception;
808 /* record initloader as initiating loader */
809 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
813 /* {this is the first resolution for this entry} */
814 /* record initloader as initiating loader */
815 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
817 /* maybe we can merge this entry with another one */
818 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
819 /* we dont want the entry that we have already */
820 if (clsenB->classobj == cls) {
821 /* this entry has the same classobj. let's merge them */
822 classcache_merge_class_entries(en,clsen,clsenB);
827 /* record the loaded class object */
828 clsen->classobj = cls;
829 CLASSCACHE_COUNT(stat_classes_stored);
838 /* {There is no class entry containing initloader as initiating
839 * or constrained loader.} */
841 /* we look for a class entry with the same classobj we want to store */
842 for (clsen = en->classes; clsen; clsen = clsen->next) {
843 if (clsen->classobj == cls) {
844 /* this entry is about the same classobj. let's use it */
845 /* check if this entry has already been loaded by initloader */
846 for (lden = clsen->loaders; lden; lden = lden->next) {
847 if (lden->loader == initloader)
850 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
855 /* create a new class entry for this class object with */
856 /* initiating loader initloader */
858 clsen = NEW(classcache_class_entry);
859 clsen->classobj = cls;
860 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
861 clsen->constraints = NULL;
863 clsen->next = en->classes;
865 CLASSCACHE_COUNT(stat_classes_stored);
868 #ifdef CLASSCACHE_VERBOSE
869 classcache_debug_dump(stderr,cls->name);
876 return NULL; /* exception */
879 /* classcache_store_unique *****************************************************
881 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
882 aroung classcache_store that throws an exception if a class with the same
883 name has already been loaded by the bootstrap loader.
885 This function is used to register a few special classes during startup.
886 It should not be used otherwise.
889 cls..............class object to cache
892 true.............everything ok, the class was stored.
893 false............an exception has been thrown.
895 Note: synchronized with global tablelock
897 *******************************************************************************/
899 bool classcache_store_unique(classinfo *cls)
903 result = classcache_store(NULL,cls,false);
908 *exceptionptr = new_internalerror("class already stored in the class cache");
915 /* classcache_store_defined ****************************************************
917 Store a loaded class after it has been defined. If the class has already
918 been defined by the same defining loader in another thread, free the given
919 class and returned the one which has been defined earlier.
922 cls..............class object to store. classloader must be set
923 (classloader may be NULL, for bootloader)
926 cls..............everything ok, the class was stored the cache,
927 other classinfo..the class had already been defined, CLS was freed, the
928 class which was defined earlier is returned,
929 NULL.............an exception has been thrown.
931 *******************************************************************************/
933 classinfo *classcache_store_defined(classinfo *cls)
935 classcache_name_entry *en;
936 classcache_class_entry *clsen;
937 #ifdef CLASSCACHE_VERBOSE
938 char logbuffer[1024];
942 assert(cls->state & CLASS_LOADED);
946 #ifdef CLASSCACHE_VERBOSE
947 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
948 utf_strcat(logbuffer, cls->name);
949 strcat(logbuffer,")");
953 en = classcache_new_name(cls->name);
957 /* iterate over all class entries */
958 for (clsen = en->classes; clsen; clsen = clsen->next) {
960 /* check if this class has been defined by the same classloader */
961 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
962 /* we found an earlier definition, delete the newer one */
963 /* (if it is a different classinfo) */
964 if (clsen->classobj != cls) {
965 #ifdef CLASSCACHE_VERBOSE
966 dolog("replacing %p with earlier defined class %p",cls,clsen->classobj);
969 cls = clsen->classobj;
975 /* create a new class entry for this class object */
976 /* the list of initiating loaders is empty at this point */
978 clsen = NEW(classcache_class_entry);
979 clsen->classobj = cls;
980 clsen->loaders = NULL;
981 clsen->constraints = NULL;
983 clsen->next = en->classes;
985 CLASSCACHE_COUNT(stat_classes_stored);
988 #ifdef CLASSCACHE_VERBOSE
989 classcache_debug_dump(stderr,cls->name);
995 /* classcache_find_loader ******************************************************
997 Find the class entry loaded by or constrained to a given loader
998 (internally used helper function)
1001 entry............the classcache_name_entry
1002 loader...........the loader to look for
1005 the classcache_class_entry for the given loader, or
1006 NULL if no entry was found
1008 *******************************************************************************/
1010 static classcache_class_entry * classcache_find_loader(
1011 classcache_name_entry * entry,
1012 classloader * loader)
1014 classcache_class_entry *clsen;
1015 classcache_loader_entry *lden;
1019 /* iterate over all class entries */
1020 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1022 /* check if this entry has already been loaded by initloader */
1023 for (lden = clsen->loaders; lden; lden = lden->next) {
1024 if (lden->loader == loader)
1025 return clsen; /* found */
1028 /* check if loader is constrained to this entry */
1029 for (lden = clsen->constraints; lden; lden = lden->next) {
1030 if (lden->loader == loader)
1031 return clsen; /* found */
1039 /* classcache_free_class_entry *************************************************
1041 Free the memory used by a class entry
1044 clsen............the classcache_class_entry to free
1046 *******************************************************************************/
1048 static void classcache_free_class_entry(classcache_class_entry * clsen)
1050 classcache_loader_entry *lden;
1051 classcache_loader_entry *next;
1055 for (lden = clsen->loaders; lden; lden = next) {
1057 FREE(lden, classcache_loader_entry);
1059 for (lden = clsen->constraints; lden; lden = next) {
1061 FREE(lden, classcache_loader_entry);
1064 FREE(clsen, classcache_class_entry);
1067 /* classcache_remove_class_entry ***********************************************
1069 Remove a classcache_class_entry from the list of possible resolution of
1071 (internally used helper function)
1074 entry............the classcache_name_entry
1075 clsen............the classcache_class_entry to remove
1077 *******************************************************************************/
1079 static void classcache_remove_class_entry(classcache_name_entry * entry,
1080 classcache_class_entry * clsen)
1082 classcache_class_entry **chain;
1087 chain = &(entry->classes);
1089 if (*chain == clsen) {
1090 *chain = clsen->next;
1091 classcache_free_class_entry(clsen);
1094 chain = &((*chain)->next);
1098 /* classcache_free_name_entry **************************************************
1100 Free the memory used by a name entry
1103 entry............the classcache_name_entry to free
1105 *******************************************************************************/
1107 static void classcache_free_name_entry(classcache_name_entry * entry)
1109 classcache_class_entry *clsen;
1110 classcache_class_entry *next;
1114 for (clsen = entry->classes; clsen; clsen = next) {
1116 classcache_free_class_entry(clsen);
1119 FREE(entry, classcache_name_entry);
1122 /* classcache_free *************************************************************
1124 Free the memory used by the class cache
1127 The class cache may not be used any more after this call, except
1128 when it is reinitialized with classcache_init.
1130 Note: NOT synchronized!
1132 *******************************************************************************/
1134 void classcache_free(void)
1137 classcache_name_entry *entry;
1138 classcache_name_entry *next;
1140 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1141 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1142 next = entry->hashlink;
1143 classcache_free_name_entry(entry);
1147 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1148 hashtable_classcache.size = 0;
1149 hashtable_classcache.entries = 0;
1150 hashtable_classcache.ptr = NULL;
1153 /* classcache_add_constraint ***************************************************
1155 Add a loading constraint
1158 a................first initiating loader
1159 b................second initiating loader
1160 classname........class name
1163 true.............everything ok, the constraint has been added,
1164 false............an exception has been thrown.
1166 Note: synchronized with global tablelock
1168 *******************************************************************************/
1170 bool classcache_add_constraint(classloader * a,
1174 classcache_name_entry *en;
1175 classcache_class_entry *clsenA;
1176 classcache_class_entry *clsenB;
1180 #ifdef CLASSCACHE_VERBOSE
1181 fprintf(stderr, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1182 utf_fprint_classname(stderr, classname);
1183 fprintf(stderr, ")\n");
1186 /* a constraint with a == b is trivially satisfied */
1188 CLASSCACHE_COUNT(stat_trivial_constraints);
1194 en = classcache_new_name(classname);
1197 CLASSCACHE_COUNT(stat_nontriv_constraints);
1199 /* find the entry loaded by / constrained to each loader */
1200 clsenA = classcache_find_loader(en, a);
1201 clsenB = classcache_find_loader(en, b);
1203 if (clsenA && clsenB) {
1204 /* { both loaders have corresponding entries } */
1205 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1207 /* if the entries are the same, the constraint is already recorded */
1208 if (clsenA == clsenB)
1209 goto return_success;
1211 /* check if the entries can be merged */
1212 if (clsenA->classobj && clsenB->classobj
1213 && clsenA->classobj != clsenB->classobj) {
1214 /* no, the constraint is violated */
1215 *exceptionptr = exceptions_new_linkageerror(
1216 "loading constraint violated: ",clsenA->classobj);
1217 goto return_exception;
1220 /* yes, merge the entries */
1221 classcache_merge_class_entries(en,clsenA,clsenB);
1222 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1225 /* { at most one of the loaders has a corresponding entry } */
1227 /* set clsenA to the single class entry we have */
1232 /* { no loader has a corresponding entry } */
1233 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1235 /* create a new class entry with the constraint (a,b,en->name) */
1236 clsenA = NEW(classcache_class_entry);
1237 clsenA->classobj = NULL;
1238 clsenA->loaders = NULL;
1239 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1240 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1242 clsenA->next = en->classes;
1243 en->classes = clsenA;
1246 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1248 /* make b the loader that has no corresponding entry */
1252 /* loader b must be added to entry clsenA */
1253 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1258 CLASSCACHE_UNLOCK();
1262 CLASSCACHE_UNLOCK();
1263 return false; /* exception */
1266 /*============================================================================*/
1268 /*============================================================================*/
1270 /* classcache_debug_dump *******************************************************
1272 Print the contents of the loaded class cache to a stream
1275 file.............output stream
1276 only.............if != NULL, only print entries for this name
1277 (Currently we print also the rest of the hash chain to
1278 get a feel for the average length of hash chains.)
1280 Note: synchronized with global tablelock
1282 *******************************************************************************/
1285 void classcache_debug_dump(FILE * file,utf *only)
1287 classcache_name_entry *c;
1288 classcache_class_entry *clsen;
1289 classcache_loader_entry *lden;
1294 fprintf(file, "\n=== [loaded class cache] =====================================\n\n");
1295 fprintf(file, "hash size : %d\n", (int) hashtable_classcache.size);
1296 fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries);
1297 fprintf(file, "\n");
1300 c = classcache_lookup_name(only);
1301 slot = 0; /* avoid compiler warning */
1305 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1306 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1309 for (; c; c = c->hashlink) {
1310 utf_fprint_classname(file, c->name);
1311 fprintf(file, "\n");
1313 /* iterate over all class entries */
1314 for (clsen = c->classes; clsen; clsen = clsen->next) {
1315 if (clsen->classobj) {
1316 fprintf(file, " loaded %p\n", (void *) clsen->classobj);
1319 fprintf(file, " unresolved\n");
1321 fprintf(file, " loaders:");
1322 for (lden = clsen->loaders; lden; lden = lden->next) {
1323 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1325 fprintf(file, "\n constraints:");
1326 for (lden = clsen->constraints; lden; lden = lden->next) {
1327 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1329 fprintf(file, "\n");
1336 fprintf(file, "\n==============================================================\n\n");
1338 CLASSCACHE_UNLOCK();
1343 * These are local overrides for various environment variables in Emacs.
1344 * Please do not remove this and leave it at the end of the file, where
1345 * Emacs will automagically detect them.
1346 * ---------------------------------------------------------------------
1349 * indent-tabs-mode: t
1353 * vim:noexpandtab:sw=4:ts=4: