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 4526 2006-02-20 14:08:26Z 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"
48 /*************************************************************************
52 The classcache has two functions:
54 1) caching the resolution of class references
55 2) storing and checking loading constraints
57 We will use the following terms in this description:
59 N a class name: a utf string
60 (N,L) a class reference with initiating loader L and class name N
61 C a class (object): the result of resolving a reference (N,L)
62 We will write resultion as
64 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
65 resolve to the same class C. So (N,L1,L2) means
68 The functions of the classcache require:
70 1) a mapping (N,L) |--> C for looking up prior resolution results.
71 2) storing the current set of loading constraints { (N,L1,L2) }
73 These functions can be rearranged like that:
75 a mapping N |--> (a mapping L |--> C or NULL,
76 a set of constraints {(L1,L2)})
78 Thus we can treat the mapping and constraints for each name N
79 separately. The implementation does this by keeping a hash table
80 mapping a name N to a `classcache_name_entry` which contains all
81 info with respect to N.
83 For a class name N we can define an equivalence relation ~N~ on
86 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
88 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
90 Also, if two references (N,L1) and (N,L2) resolve to the same class C
91 we have L1 ~N~ L2 because class loaders are required to return
92 consistent resolutions for a name N [XXX].
94 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
96 Cx...is a class C or NULL
97 IL...is the set of initiating loaders
98 CL...is the set of constrained loaders
100 Such a tuple is called `classcache_class_entry` in the source code.
102 The following holds for each tuple (Cx,IL,CL):
104 . (Cx is NULL) implies IL = {}.
106 . If Cx is a class, IL is the set of loaders that have been
107 recorded as initiating loaders for Cx. IL may be the
108 empty set {} in case Cx has already been defined but no
109 initiating loader has been recorded, yet.
111 . (IL u CL) is a subset of an equivalence class of ~N~.
113 (This means that all loaders in IL and CL must resolve
114 the name N to the same class.)
116 The following holds for the set of tuples { (Cx,IL,CL) }:
118 . For a given class C there is at most one tuple with Cx = C
119 in the set. (There may be an arbitrary number of tuples
120 with Cx = NULL, however.)
122 . For a given loader L there is at most one tuple with
125 The implementation stores sets of loaders as linked lists of
126 `classcache_loader_entry`s.
128 Comments about manipulating the classcache can be found in the
129 individual functions below.
131 *************************************************************************/
134 /* initial number of slots in the classcache hash table */
135 #define CLASSCACHE_INIT_SIZE 2048
137 /*============================================================================*/
139 /*============================================================================*/
141 /*#define CLASSCACHE_VERBOSE*/
143 /*============================================================================*/
145 /*============================================================================*/
147 /*#define CLASSCACHE_STATS*/
149 #ifdef CLASSCACHE_STATS
150 static int stat_classnames_stored = 0;
151 static int stat_classes_stored = 0;
152 static int stat_trivial_constraints = 0;
153 static int stat_nontriv_constraints = 0;
154 static int stat_nontriv_constraints_both = 0;
155 static int stat_nontriv_constraints_merged = 0;
156 static int stat_nontriv_constraints_one = 0;
157 static int stat_nontriv_constraints_none = 0;
158 static int stat_new_loader_entry = 0;
159 static int stat_merge_class_entries = 0;
160 static int stat_merge_loader_entries = 0;
161 static int stat_lookup = 0;
162 static int stat_lookup_class_entry_checked = 0;
163 static int stat_lookup_loader_checked = 0;
164 static int stat_lookup_name = 0;
165 static int stat_lookup_name_entry = 0;
166 static int stat_lookup_name_notfound = 0;
167 static int stat_lookup_new_name = 0;
168 static int stat_lookup_new_name_entry = 0;
169 static int stat_lookup_new_name_collisions = 0;
170 static int stat_rehash_names = 0;
171 static int stat_rehash_names_collisions = 0;
173 #define CLASSCACHE_COUNT(cnt) (cnt)++
174 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
176 void classcache_print_statistics(FILE *file) {
177 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
178 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
179 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
180 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
181 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
182 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
183 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
184 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
185 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
186 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
187 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
188 fprintf(file,"lookups : %8d\n",stat_lookup);
189 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
190 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
191 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
192 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
193 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
194 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
195 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
196 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
197 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
198 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
201 #define CLASSCACHE_COUNT(cnt)
202 #define CLASSCACHE_COUNTIF(cond,cnt)
205 /*============================================================================*/
206 /* THREAD-SAFE LOCKING */
207 /*============================================================================*/
209 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
210 /* CAUTION: The static functions below are */
211 /* NOT synchronized! */
212 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
214 #if defined(USE_THREADS)
215 # define CLASSCACHE_LOCK() builtin_monitorenter(lock_hashtable_classcache)
216 # define CLASSCACHE_UNLOCK() builtin_monitorexit(lock_hashtable_classcache)
218 # define CLASSCACHE_LOCK()
219 # define CLASSCACHE_UNLOCK()
222 /*============================================================================*/
223 /* GLOBAL VARIABLES */
224 /*============================================================================*/
226 hashtable hashtable_classcache;
228 #if defined(USE_THREADS)
229 static java_objectheader *lock_hashtable_classcache;
233 /*============================================================================*/
235 /*============================================================================*/
239 static void classcache_free_class_entry(classcache_class_entry *clsen);
240 static void classcache_remove_class_entry(classcache_name_entry *en,
241 classcache_class_entry *clsen);
243 /* hash function to use */
245 #define CLASSCACHE_HASH utf_full_hashkey
247 /* classcache_init *************************************************************
249 Initialize the class cache
251 Note: NOT synchronized!
253 *******************************************************************************/
255 bool classcache_init(void)
257 /* create the hashtable */
259 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
261 #if defined(USE_THREADS)
262 /* create utf hashtable lock object */
264 lock_hashtable_classcache = NEW(java_objectheader);
266 # if defined(NATIVE_THREADS)
267 initObjectLock(lock_hashtable_classcache);
271 /* everything's ok */
276 /* classcache_new_loader_entry *************************************************
278 Create a new classcache_loader_entry struct
279 (internally used helper function)
282 loader...........the ClassLoader object
283 next.............the next classcache_loader_entry
286 the new classcache_loader_entry
288 *******************************************************************************/
290 static classcache_loader_entry * classcache_new_loader_entry(
291 classloader * loader,
292 classcache_loader_entry * next)
294 classcache_loader_entry *lden;
296 lden = NEW(classcache_loader_entry);
297 lden->loader = loader;
299 CLASSCACHE_COUNT(stat_new_loader_entry);
304 /* classcache_merge_loaders ****************************************************
306 Merge two lists of loaders into one
307 (internally used helper function)
310 lista............first list (may be NULL)
311 listb............second list (may be NULL)
314 the merged list (may be NULL)
317 The lists given as arguments are destroyed!
319 *******************************************************************************/
321 static classcache_loader_entry * classcache_merge_loaders(
322 classcache_loader_entry * lista,
323 classcache_loader_entry * listb)
325 classcache_loader_entry *result;
326 classcache_loader_entry *ldenA;
327 classcache_loader_entry *ldenB;
328 classcache_loader_entry **chain;
330 CLASSCACHE_COUNT(stat_merge_loader_entries);
332 /* XXX This is a quadratic algorithm. If this ever
333 * becomes a problem, the loader lists should be
334 * stored as sorted lists and merged in linear time. */
339 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
341 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
342 if (ldenB->loader == ldenA->loader)
346 /* this loader is only in lista */
348 chain = &(ldenA->next);
351 /* XXX free the duplicated element */
355 /* concat listb to the result */
361 /* classcache_merge_class_entries **********************************************
363 Merge two `classcache_class_entry`s into one.
364 (internally used helper function)
367 en...............the classcache_name_entry containing both class entries
368 clsenA...........first class entry, will receive the result
369 clsenB...........second class entry
372 Either both entries must have the same classobj, or one of them has
376 clsenB is freed by this function!
378 *******************************************************************************/
380 static void classcache_merge_class_entries(classcache_name_entry *en,
381 classcache_class_entry *clsenA,
382 classcache_class_entry *clsenB)
384 #ifdef CLASSCACHE_VERBOSE
385 char logbuffer[1024];
391 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
393 #ifdef CLASSCACHE_VERBOSE
394 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
395 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
396 if (clsenA->classobj)
397 utf_strcat(logbuffer, clsenA->classobj->name);
398 if (clsenB->classobj)
399 utf_strcat(logbuffer, clsenB->classobj->name);
403 CLASSCACHE_COUNT(stat_merge_class_entries);
405 /* clsenB will be merged into clsenA */
406 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
407 clsenB->loaders = NULL; /* these have been freed or reused */
409 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
410 clsenB->constraints);
411 clsenB->constraints = NULL; /* these have been freed or reused */
413 if (!clsenA->classobj)
414 clsenA->classobj = clsenB->classobj;
416 /* remove clsenB from the list of class entries */
417 classcache_remove_class_entry(en, clsenB);
421 /* classcache_lookup_name ******************************************************
423 Lookup a name in the first level of the cache
424 (internally used helper function)
427 name.............the name to look up
430 a pointer to the classcache_name_entry for this name, or
431 null if no entry was found.
433 *******************************************************************************/
435 static classcache_name_entry *classcache_lookup_name(utf *name)
437 classcache_name_entry *c; /* hash table element */
438 u4 key; /* hashkey computed from classname */
439 u4 slot; /* slot in hashtable */
441 CLASSCACHE_COUNT(stat_lookup_name);
443 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
444 slot = key & (hashtable_classcache.size - 1);
445 c = hashtable_classcache.ptr[slot];
447 /* search external hash chain for the entry */
450 /* entry found in hashtable */
451 CLASSCACHE_COUNT(stat_lookup_name_entry);
456 c = c->hashlink; /* next element in external chain */
461 CLASSCACHE_COUNT(stat_lookup_name_notfound);
466 /* classcache_new_name *********************************************************
468 Return a classcache_name_entry for the given name. The entry is created
469 if it is not already in the cache.
470 (internally used helper function)
473 name.............the name to look up / create an entry for
476 a pointer to the classcache_name_entry for this name
478 *******************************************************************************/
480 static classcache_name_entry *classcache_new_name(utf *name)
482 classcache_name_entry *c; /* hash table element */
483 u4 key; /* hashkey computed from classname */
484 u4 slot; /* slot in hashtable */
487 CLASSCACHE_COUNT(stat_lookup_new_name);
489 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
490 slot = key & (hashtable_classcache.size - 1);
491 c = hashtable_classcache.ptr[slot];
493 /* search external hash chain for the entry */
496 /* entry found in hashtable */
497 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
502 c = c->hashlink; /* next element in external chain */
505 /* location in hashtable found, create new entry */
507 c = NEW(classcache_name_entry);
512 /* insert entry into hashtable */
513 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
514 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
515 hashtable_classcache.ptr[slot] = c;
517 /* update number of hashtable-entries */
518 hashtable_classcache.entries++;
519 CLASSCACHE_COUNT(stat_classnames_stored);
521 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
522 /* reorganization of hashtable */
524 classcache_name_entry *c2;
525 hashtable newhash; /* the new hashtable */
527 CLASSCACHE_COUNT(stat_rehash_names);
529 /* create new hashtable, double the size */
531 hashtable_create(&newhash, hashtable_classcache.size * 2);
532 newhash.entries = hashtable_classcache.entries;
534 /* transfer elements to new hashtable */
536 for (i = 0; i < hashtable_classcache.size; i++) {
537 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
539 classcache_name_entry *nextc = c2->hashlink;
541 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
543 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
544 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
545 newhash.ptr[newslot] = c2;
551 /* dispose old table */
553 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
554 hashtable_classcache = newhash;
561 /* classcache_lookup ***********************************************************
563 Lookup a possibly loaded class
566 initloader.......initiating loader for resolving the class name
567 classname........class name to look up
570 The return value is a pointer to the cached class object,
571 or NULL, if the class is not in the cache.
573 Note: synchronized with global tablelock
575 *******************************************************************************/
577 classinfo *classcache_lookup(classloader *initloader, utf *classname)
579 classcache_name_entry *en;
580 classcache_class_entry *clsen;
581 classcache_loader_entry *lden;
582 classinfo *cls = NULL;
586 CLASSCACHE_COUNT(stat_lookup);
587 en = classcache_lookup_name(classname);
590 /* iterate over all class entries */
592 for (clsen = en->classes; clsen; clsen = clsen->next) {
593 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
594 /* check if this entry has been loaded by initloader */
596 for (lden = clsen->loaders; lden; lden = lden->next) {
597 CLASSCACHE_COUNT(stat_lookup_loader_checked);
598 if (lden->loader == initloader) {
599 /* found the loaded class entry */
601 assert(clsen->classobj);
602 cls = clsen->classobj;
615 /* classcache_lookup_defined ***************************************************
617 Lookup a class with the given name and defining loader
620 defloader........defining loader
621 classname........class name
624 The return value is a pointer to the cached class object,
625 or NULL, if the class is not in the cache.
627 *******************************************************************************/
629 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
631 classcache_name_entry *en;
632 classcache_class_entry *clsen;
633 classinfo *cls = NULL;
637 en = classcache_lookup_name(classname);
640 /* iterate over all class entries */
641 for (clsen = en->classes; clsen; clsen = clsen->next) {
642 if (!clsen->classobj)
645 /* check if this entry has been defined by defloader */
646 if (clsen->classobj->classloader == defloader) {
647 cls = clsen->classobj;
659 /* classcache_lookup_defined_or_initiated **************************************
661 Lookup a class that has been defined or initiated by the given loader
664 loader...........defining or initiating loader
665 classname........class name to look up
668 The return value is a pointer to the cached class object,
669 or NULL, if the class is not in the cache.
671 Note: synchronized with global tablelock
673 *******************************************************************************/
675 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
678 classcache_name_entry *en;
679 classcache_class_entry *clsen;
680 classcache_loader_entry *lden;
681 classinfo *cls = NULL;
685 en = classcache_lookup_name(classname);
688 /* iterate over all class entries */
690 for (clsen = en->classes; clsen; clsen = clsen->next) {
692 /* check if this entry has been defined by loader */
693 if (clsen->classobj && clsen->classobj->classloader == loader) {
694 cls = clsen->classobj;
698 /* check if this entry has been initiated by loader */
699 for (lden = clsen->loaders; lden; lden = lden->next) {
700 if (lden->loader == loader) {
701 /* found the loaded class entry */
703 assert(clsen->classobj);
704 cls = clsen->classobj;
717 /* classcache_store ************************************************************
719 Store a loaded class. If a class of the same name has already been stored
720 with the same initiating loader, then the given class CLS is freed (if
721 possible) and the previously stored class is returned.
724 initloader.......initiating loader used to load the class
725 (may be NULL indicating the bootstrap loader)
726 cls..............class object to cache
727 mayfree..........true if CLS may be freed in case another class is
731 cls..............everything ok, the class was stored in the cache,
732 other classinfo..another class with the same (initloader,name) has been
733 stored earlier. CLS has been freed[1] and the earlier
734 stored class is returned.
735 NULL.............an exception has been thrown.
737 Note: synchronized with global tablelock
739 [1]...in case MAYFREE is true
741 *******************************************************************************/
743 classinfo *classcache_store(classloader *initloader, classinfo *cls,
746 classcache_name_entry *en;
747 classcache_class_entry *clsen;
748 classcache_class_entry *clsenB;
749 classcache_loader_entry *lden;
750 #ifdef CLASSCACHE_VERBOSE
751 char logbuffer[1024];
755 assert(cls->state & CLASS_LOADED);
759 #ifdef CLASSCACHE_VERBOSE
760 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
761 utf_strcat(logbuffer, cls->name);
762 strcat(logbuffer,")");
766 en = classcache_new_name(cls->name);
770 /* iterate over all class entries */
771 for (clsen = en->classes; clsen; clsen = clsen->next) {
773 /* check if this entry has already been loaded by initloader */
774 for (lden = clsen->loaders; lden; lden = lden->next) {
775 if (lden->loader == initloader) {
776 if (clsen->classobj != cls) {
777 /* A class with the same (initloader,name) pair has been stored already. */
778 /* We free the given class and return the earlier one. */
779 #ifdef CLASSCACHE_VERBOSE
780 dolog("replacing %p with earlier loaded class %p",cls,clsen->classobj);
782 assert(clsen->classobj);
785 cls = clsen->classobj;
791 /* {This entry has not been resolved with initloader} */
793 /* check if initloader is constrained to this entry */
794 for (lden = clsen->constraints; lden; lden = lden->next) {
795 if (lden->loader == initloader) {
796 /* we have to use this entry. check if it has been resolved */
797 if (clsen->classobj) {
798 /* check if is has already been resolved to another class */
799 if (clsen->classobj != cls) {
800 /* a loading constraint is violated */
801 *exceptionptr = exceptions_new_linkageerror(
802 "loading constraint violated: ",cls);
803 goto return_exception;
806 /* record initloader as initiating loader */
807 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
811 /* {this is the first resolution for this entry} */
812 /* record initloader as initiating loader */
813 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
815 /* maybe we can merge this entry with another one */
816 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
817 /* we dont want the entry that we have already */
818 if (clsenB->classobj == cls) {
819 /* this entry has the same classobj. let's merge them */
820 classcache_merge_class_entries(en,clsen,clsenB);
825 /* record the loaded class object */
826 clsen->classobj = cls;
827 CLASSCACHE_COUNT(stat_classes_stored);
836 /* {There is no class entry containing initloader as initiating
837 * or constrained loader.} */
839 /* we look for a class entry with the same classobj we want to store */
840 for (clsen = en->classes; clsen; clsen = clsen->next) {
841 if (clsen->classobj == cls) {
842 /* this entry is about the same classobj. let's use it */
843 /* check if this entry has already been loaded by initloader */
844 for (lden = clsen->loaders; lden; lden = lden->next) {
845 if (lden->loader == initloader)
848 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
853 /* create a new class entry for this class object with */
854 /* initiating loader initloader */
856 clsen = NEW(classcache_class_entry);
857 clsen->classobj = cls;
858 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
859 clsen->constraints = NULL;
861 clsen->next = en->classes;
863 CLASSCACHE_COUNT(stat_classes_stored);
866 #ifdef CLASSCACHE_VERBOSE
867 classcache_debug_dump(stderr,cls->name);
874 return NULL; /* exception */
877 /* classcache_store_unique *****************************************************
879 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
880 aroung classcache_store that throws an exception if a class with the same
881 name has already been loaded by the bootstrap loader.
883 This function is used to register a few special classes during startup.
884 It should not be used otherwise.
887 cls..............class object to cache
890 true.............everything ok, the class was stored.
891 false............an exception has been thrown.
893 Note: synchronized with global tablelock
895 *******************************************************************************/
897 bool classcache_store_unique(classinfo *cls)
901 result = classcache_store(NULL,cls,false);
906 *exceptionptr = new_internalerror("class already stored in the class cache");
913 /* classcache_store_defined ****************************************************
915 Store a loaded class after it has been defined. If the class has already
916 been defined by the same defining loader in another thread, free the given
917 class and returned the one which has been defined earlier.
920 cls..............class object to store. classloader must be set
921 (classloader may be NULL, for bootloader)
924 cls..............everything ok, the class was stored the cache,
925 other classinfo..the class had already been defined, CLS was freed, the
926 class which was defined earlier is returned,
927 NULL.............an exception has been thrown.
929 *******************************************************************************/
931 classinfo *classcache_store_defined(classinfo *cls)
933 classcache_name_entry *en;
934 classcache_class_entry *clsen;
935 #ifdef CLASSCACHE_VERBOSE
936 char logbuffer[1024];
940 assert(cls->state & CLASS_LOADED);
944 #ifdef CLASSCACHE_VERBOSE
945 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
946 utf_strcat(logbuffer, cls->name);
947 strcat(logbuffer,")");
951 en = classcache_new_name(cls->name);
955 /* iterate over all class entries */
956 for (clsen = en->classes; clsen; clsen = clsen->next) {
958 /* check if this class has been defined by the same classloader */
959 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
960 /* we found an earlier definition, delete the newer one */
961 /* (if it is a different classinfo) */
962 if (clsen->classobj != cls) {
963 #ifdef CLASSCACHE_VERBOSE
964 dolog("replacing %p with earlier defined class %p",cls,clsen->classobj);
967 cls = clsen->classobj;
973 /* create a new class entry for this class object */
974 /* the list of initiating loaders is empty at this point */
976 clsen = NEW(classcache_class_entry);
977 clsen->classobj = cls;
978 clsen->loaders = NULL;
979 clsen->constraints = NULL;
981 clsen->next = en->classes;
983 CLASSCACHE_COUNT(stat_classes_stored);
986 #ifdef CLASSCACHE_VERBOSE
987 classcache_debug_dump(stderr,cls->name);
993 /* classcache_find_loader ******************************************************
995 Find the class entry loaded by or constrained to a given loader
996 (internally used helper function)
999 entry............the classcache_name_entry
1000 loader...........the loader to look for
1003 the classcache_class_entry for the given loader, or
1004 NULL if no entry was found
1006 *******************************************************************************/
1008 static classcache_class_entry * classcache_find_loader(
1009 classcache_name_entry * entry,
1010 classloader * loader)
1012 classcache_class_entry *clsen;
1013 classcache_loader_entry *lden;
1017 /* iterate over all class entries */
1018 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1020 /* check if this entry has already been loaded by initloader */
1021 for (lden = clsen->loaders; lden; lden = lden->next) {
1022 if (lden->loader == loader)
1023 return clsen; /* found */
1026 /* check if loader is constrained to this entry */
1027 for (lden = clsen->constraints; lden; lden = lden->next) {
1028 if (lden->loader == loader)
1029 return clsen; /* found */
1037 /* classcache_free_class_entry *************************************************
1039 Free the memory used by a class entry
1042 clsen............the classcache_class_entry to free
1044 *******************************************************************************/
1046 static void classcache_free_class_entry(classcache_class_entry * clsen)
1048 classcache_loader_entry *lden;
1049 classcache_loader_entry *next;
1053 for (lden = clsen->loaders; lden; lden = next) {
1055 FREE(lden, classcache_loader_entry);
1057 for (lden = clsen->constraints; lden; lden = next) {
1059 FREE(lden, classcache_loader_entry);
1062 FREE(clsen, classcache_class_entry);
1065 /* classcache_remove_class_entry ***********************************************
1067 Remove a classcache_class_entry from the list of possible resolution of
1069 (internally used helper function)
1072 entry............the classcache_name_entry
1073 clsen............the classcache_class_entry to remove
1075 *******************************************************************************/
1077 static void classcache_remove_class_entry(classcache_name_entry * entry,
1078 classcache_class_entry * clsen)
1080 classcache_class_entry **chain;
1085 chain = &(entry->classes);
1087 if (*chain == clsen) {
1088 *chain = clsen->next;
1089 classcache_free_class_entry(clsen);
1092 chain = &((*chain)->next);
1096 /* classcache_free_name_entry **************************************************
1098 Free the memory used by a name entry
1101 entry............the classcache_name_entry to free
1103 *******************************************************************************/
1105 static void classcache_free_name_entry(classcache_name_entry * entry)
1107 classcache_class_entry *clsen;
1108 classcache_class_entry *next;
1112 for (clsen = entry->classes; clsen; clsen = next) {
1114 classcache_free_class_entry(clsen);
1117 FREE(entry, classcache_name_entry);
1120 /* classcache_free *************************************************************
1122 Free the memory used by the class cache
1125 The class cache may not be used any more after this call, except
1126 when it is reinitialized with classcache_init.
1128 Note: NOT synchronized!
1130 *******************************************************************************/
1132 void classcache_free(void)
1135 classcache_name_entry *entry;
1136 classcache_name_entry *next;
1138 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1139 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1140 next = entry->hashlink;
1141 classcache_free_name_entry(entry);
1145 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1146 hashtable_classcache.size = 0;
1147 hashtable_classcache.entries = 0;
1148 hashtable_classcache.ptr = NULL;
1151 /* classcache_add_constraint ***************************************************
1153 Add a loading constraint
1156 a................first initiating loader
1157 b................second initiating loader
1158 classname........class name
1161 true.............everything ok, the constraint has been added,
1162 false............an exception has been thrown.
1164 Note: synchronized with global tablelock
1166 *******************************************************************************/
1168 bool classcache_add_constraint(classloader * a,
1172 classcache_name_entry *en;
1173 classcache_class_entry *clsenA;
1174 classcache_class_entry *clsenB;
1178 #ifdef CLASSCACHE_VERBOSE
1179 fprintf(stderr, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1180 utf_fprint_classname(stderr, classname);
1181 fprintf(stderr, ")\n");
1184 /* a constraint with a == b is trivially satisfied */
1186 CLASSCACHE_COUNT(stat_trivial_constraints);
1192 en = classcache_new_name(classname);
1195 CLASSCACHE_COUNT(stat_nontriv_constraints);
1197 /* find the entry loaded by / constrained to each loader */
1198 clsenA = classcache_find_loader(en, a);
1199 clsenB = classcache_find_loader(en, b);
1201 if (clsenA && clsenB) {
1202 /* { both loaders have corresponding entries } */
1203 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1205 /* if the entries are the same, the constraint is already recorded */
1206 if (clsenA == clsenB)
1207 goto return_success;
1209 /* check if the entries can be merged */
1210 if (clsenA->classobj && clsenB->classobj
1211 && clsenA->classobj != clsenB->classobj) {
1212 /* no, the constraint is violated */
1213 *exceptionptr = exceptions_new_linkageerror(
1214 "loading constraint violated: ",clsenA->classobj);
1215 goto return_exception;
1218 /* yes, merge the entries */
1219 classcache_merge_class_entries(en,clsenA,clsenB);
1220 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1223 /* { at most one of the loaders has a corresponding entry } */
1225 /* set clsenA to the single class entry we have */
1230 /* { no loader has a corresponding entry } */
1231 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1233 /* create a new class entry with the constraint (a,b,en->name) */
1234 clsenA = NEW(classcache_class_entry);
1235 clsenA->classobj = NULL;
1236 clsenA->loaders = NULL;
1237 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1238 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1240 clsenA->next = en->classes;
1241 en->classes = clsenA;
1244 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1246 /* make b the loader that has no corresponding entry */
1250 /* loader b must be added to entry clsenA */
1251 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1256 CLASSCACHE_UNLOCK();
1260 CLASSCACHE_UNLOCK();
1261 return false; /* exception */
1264 /*============================================================================*/
1266 /*============================================================================*/
1268 /* classcache_debug_dump *******************************************************
1270 Print the contents of the loaded class cache to a stream
1273 file.............output stream
1274 only.............if != NULL, only print entries for this name
1275 (Currently we print also the rest of the hash chain to
1276 get a feel for the average length of hash chains.)
1278 Note: synchronized with global tablelock
1280 *******************************************************************************/
1283 void classcache_debug_dump(FILE * file,utf *only)
1285 classcache_name_entry *c;
1286 classcache_class_entry *clsen;
1287 classcache_loader_entry *lden;
1292 fprintf(file, "\n=== [loaded class cache] =====================================\n\n");
1293 fprintf(file, "hash size : %d\n", (int) hashtable_classcache.size);
1294 fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries);
1295 fprintf(file, "\n");
1298 c = classcache_lookup_name(only);
1299 slot = 0; /* avoid compiler warning */
1303 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1304 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1307 for (; c; c = c->hashlink) {
1308 utf_fprint_classname(file, c->name);
1309 fprintf(file, "\n");
1311 /* iterate over all class entries */
1312 for (clsen = c->classes; clsen; clsen = clsen->next) {
1313 if (clsen->classobj) {
1314 fprintf(file, " loaded %p\n", (void *) clsen->classobj);
1317 fprintf(file, " unresolved\n");
1319 fprintf(file, " loaders:");
1320 for (lden = clsen->loaders; lden; lden = lden->next) {
1321 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1323 fprintf(file, "\n constraints:");
1324 for (lden = clsen->constraints; lden; lden = lden->next) {
1325 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1327 fprintf(file, "\n");
1334 fprintf(file, "\n==============================================================\n\n");
1336 CLASSCACHE_UNLOCK();
1341 * These are local overrides for various environment variables in Emacs.
1342 * Please do not remove this and leave it at the end of the file, where
1343 * Emacs will automagically detect them.
1344 * ---------------------------------------------------------------------
1347 * indent-tabs-mode: t
1351 * vim:noexpandtab:sw=4:ts=4: