1 /* src/vm/classcache.cpp - loaded class cache and loading constraints
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "mm/memory.h"
34 #include "threads/lock.hpp"
35 #include "threads/mutex.hpp"
37 #include "toolbox/hashtable.h"
38 #include "toolbox/logging.h"
40 #include "vm/classcache.hpp"
41 #include "vm/exceptions.hpp"
42 #include "vm/options.h"
46 /*************************************************************************
50 The classcache has two functions:
52 1) caching the resolution of class references
53 2) storing and checking loading constraints
55 We will use the following terms in this description:
57 N a class name: a utf string
58 (N,L) a class reference with initiating loader L and class name N
59 C a class (object): the result of resolving a reference (N,L)
60 We will write resultion as
62 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
63 resolve to the same class C. So (N,L1,L2) means
66 The functions of the classcache require:
68 1) a mapping (N,L) |--> C for looking up prior resolution results.
69 2) storing the current set of loading constraints { (N,L1,L2) }
71 These functions can be rearranged like that:
73 a mapping N |--> (a mapping L |--> C or NULL,
74 a set of constraints {(L1,L2)})
76 Thus we can treat the mapping and constraints for each name N
77 separately. The implementation does this by keeping a hash table
78 mapping a name N to a `classcache_name_entry` which contains all
79 info with respect to N.
81 For a class name N we can define an equivalence relation ~N~ on
84 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
86 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
88 Also, if two references (N,L1) and (N,L2) resolve to the same class C
89 we have L1 ~N~ L2 because class loaders are required to return
90 consistent resolutions for a name N [XXX].
92 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
94 Cx...is a class C or NULL
95 IL...is the set of initiating loaders
96 CL...is the set of constrained loaders
98 Such a tuple is called `classcache_class_entry` in the source code.
100 The following holds for each tuple (Cx,IL,CL):
102 . (Cx is NULL) implies IL = {}.
104 . If Cx is a class, IL is the set of loaders that have been
105 recorded as initiating loaders for Cx. IL may be the
106 empty set {} in case Cx has already been defined but no
107 initiating loader has been recorded, yet.
109 . (IL u CL) is a subset of an equivalence class of ~N~.
111 (This means that all loaders in IL and CL must resolve
112 the name N to the same class.)
114 The following holds for the set of tuples { (Cx,IL,CL) }:
116 . For a given class C there is at most one tuple with Cx = C
117 in the set. (There may be an arbitrary number of tuples
118 with Cx = NULL, however.)
120 . For a given loader L there is at most one tuple with
123 The implementation stores sets of loaders as linked lists of
124 `classcache_loader_entry`s.
126 Comments about manipulating the classcache can be found in the
127 individual functions below.
129 *************************************************************************/
132 /* initial number of slots in the classcache hash table */
133 #define CLASSCACHE_INIT_SIZE 2048
135 /*============================================================================*/
137 /*============================================================================*/
139 /* #define CLASSCACHE_VERBOSE */
141 #if defined(__cplusplus)
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(ENABLE_THREADS)
217 # define CLASSCACHE_LOCK() classcache_hashtable_mutex->lock();
218 # define CLASSCACHE_UNLOCK() classcache_hashtable_mutex->unlock();
220 # define CLASSCACHE_LOCK()
221 # define CLASSCACHE_UNLOCK()
224 /*============================================================================*/
225 /* GLOBAL VARIABLES */
226 /*============================================================================*/
228 hashtable hashtable_classcache;
230 #if defined(ENABLE_THREADS)
231 static Mutex *classcache_hashtable_mutex;
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 TRACESUBSYSTEMINITIALIZATION("classcache_init");
261 /* create the hashtable */
263 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
265 #if defined(ENABLE_THREADS)
266 /* create utf hashtable mutex */
268 classcache_hashtable_mutex = new Mutex();
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_t * 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_cat_classname(logbuffer, clsenA->classobj->name);
398 if (clsenB->classobj)
399 utf_cat_classname(logbuffer, clsenB->classobj->name);
400 log_println(logbuffer);
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 = (classcache_name_entry*) 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 = (classcache_name_entry*) 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_t *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_t *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_t *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_t *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_cat_classname(logbuffer, cls->name);
762 strcat(logbuffer,")");
763 log_println(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 log_println("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 exceptions_throw_linkageerror("loading constraint violated: ", cls);
802 goto return_exception;
805 /* record initloader as initiating loader */
806 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
810 /* {this is the first resolution for this entry} */
811 /* record initloader as initiating loader */
812 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
814 /* maybe we can merge this entry with another one */
815 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
816 /* we dont want the entry that we have already */
817 if (clsenB->classobj == cls) {
818 /* this entry has the same classobj. let's merge them */
819 classcache_merge_class_entries(en,clsen,clsenB);
824 /* record the loaded class object */
825 clsen->classobj = cls;
826 CLASSCACHE_COUNT(stat_classes_stored);
835 /* {There is no class entry containing initloader as initiating
836 * or constrained loader.} */
838 /* we look for a class entry with the same classobj we want to store */
839 for (clsen = en->classes; clsen; clsen = clsen->next) {
840 if (clsen->classobj == cls) {
841 /* this entry is about the same classobj. let's use it */
842 /* check if this entry has already been loaded by initloader */
843 for (lden = clsen->loaders; lden; lden = lden->next) {
844 if (lden->loader == initloader)
847 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
852 /* create a new class entry for this class object with */
853 /* initiating loader initloader */
855 clsen = NEW(classcache_class_entry);
856 clsen->classobj = cls;
857 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
858 clsen->constraints = NULL;
860 clsen->next = en->classes;
862 CLASSCACHE_COUNT(stat_classes_stored);
865 #ifdef CLASSCACHE_VERBOSE
866 classcache_debug_dump(stdout,cls->name);
873 return NULL; /* exception */
876 /* classcache_store_unique *****************************************************
878 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
879 aroung classcache_store that throws an exception if a class with the same
880 name has already been loaded by the bootstrap loader.
882 This function is used to register a few special classes during startup.
883 It should not be used otherwise.
886 cls..............class object to cache
889 true.............everything ok, the class was stored.
890 false............an exception has been thrown.
892 Note: synchronized with global tablelock
894 *******************************************************************************/
896 bool classcache_store_unique(classinfo *cls)
900 result = classcache_store(NULL,cls,false);
905 exceptions_throw_internalerror("class already stored in the class cache");
912 /* classcache_store_defined ****************************************************
914 Store a loaded class after it has been defined. If the class has already
915 been defined by the same defining loader in another thread, free the given
916 class and returned the one which has been defined earlier.
919 cls..............class object to store. classloader must be set
920 (classloader may be NULL, for bootloader)
923 cls..............everything ok, the class was stored the cache,
924 other classinfo..the class had already been defined, CLS was freed, the
925 class which was defined earlier is returned,
926 NULL.............an exception has been thrown.
928 *******************************************************************************/
930 classinfo *classcache_store_defined(classinfo *cls)
932 classcache_name_entry *en;
933 classcache_class_entry *clsen;
934 #ifdef CLASSCACHE_VERBOSE
935 char logbuffer[1024];
939 assert(cls->state & CLASS_LOADED);
943 #ifdef CLASSCACHE_VERBOSE
944 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
945 utf_cat_classname(logbuffer, cls->name);
946 strcat(logbuffer,")");
947 log_println(logbuffer);
950 en = classcache_new_name(cls->name);
954 /* iterate over all class entries */
955 for (clsen = en->classes; clsen; clsen = clsen->next) {
957 /* check if this class has been defined by the same classloader */
958 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
959 /* we found an earlier definition, delete the newer one */
960 /* (if it is a different classinfo) */
961 if (clsen->classobj != cls) {
962 #ifdef CLASSCACHE_VERBOSE
963 log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
966 cls = clsen->classobj;
972 /* create a new class entry for this class object */
973 /* the list of initiating loaders is empty at this point */
975 clsen = NEW(classcache_class_entry);
976 clsen->classobj = cls;
977 clsen->loaders = NULL;
978 clsen->constraints = NULL;
980 clsen->next = en->classes;
982 CLASSCACHE_COUNT(stat_classes_stored);
985 #ifdef CLASSCACHE_VERBOSE
986 classcache_debug_dump(stdout,cls->name);
992 /* classcache_find_loader ******************************************************
994 Find the class entry loaded by or constrained to a given loader
995 (internally used helper function)
998 entry............the classcache_name_entry
999 loader...........the loader to look for
1002 the classcache_class_entry for the given loader, or
1003 NULL if no entry was found
1005 *******************************************************************************/
1007 static classcache_class_entry * classcache_find_loader(
1008 classcache_name_entry * entry,
1009 classloader_t * loader)
1011 classcache_class_entry *clsen;
1012 classcache_loader_entry *lden;
1016 /* iterate over all class entries */
1017 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1019 /* check if this entry has already been loaded by initloader */
1020 for (lden = clsen->loaders; lden; lden = lden->next) {
1021 if (lden->loader == loader)
1022 return clsen; /* found */
1025 /* check if loader is constrained to this entry */
1026 for (lden = clsen->constraints; lden; lden = lden->next) {
1027 if (lden->loader == loader)
1028 return clsen; /* found */
1036 /* classcache_free_class_entry *************************************************
1038 Free the memory used by a class entry
1041 clsen............the classcache_class_entry to free
1043 *******************************************************************************/
1045 static void classcache_free_class_entry(classcache_class_entry * clsen)
1047 classcache_loader_entry *lden;
1048 classcache_loader_entry *next;
1052 for (lden = clsen->loaders; lden; lden = next) {
1054 FREE(lden, classcache_loader_entry);
1056 for (lden = clsen->constraints; lden; lden = next) {
1058 FREE(lden, classcache_loader_entry);
1061 FREE(clsen, classcache_class_entry);
1064 /* classcache_remove_class_entry ***********************************************
1066 Remove a classcache_class_entry from the list of possible resolution of
1068 (internally used helper function)
1071 entry............the classcache_name_entry
1072 clsen............the classcache_class_entry to remove
1074 *******************************************************************************/
1076 static void classcache_remove_class_entry(classcache_name_entry * entry,
1077 classcache_class_entry * clsen)
1079 classcache_class_entry **chain;
1084 chain = &(entry->classes);
1086 if (*chain == clsen) {
1087 *chain = clsen->next;
1088 classcache_free_class_entry(clsen);
1091 chain = &((*chain)->next);
1095 /* classcache_free_name_entry **************************************************
1097 Free the memory used by a name entry
1100 entry............the classcache_name_entry to free
1102 *******************************************************************************/
1104 static void classcache_free_name_entry(classcache_name_entry * entry)
1106 classcache_class_entry *clsen;
1107 classcache_class_entry *next;
1111 for (clsen = entry->classes; clsen; clsen = next) {
1113 classcache_free_class_entry(clsen);
1116 FREE(entry, classcache_name_entry);
1119 /* classcache_free *************************************************************
1121 Free the memory used by the class cache
1124 The class cache may not be used any more after this call, except
1125 when it is reinitialized with classcache_init.
1127 Note: NOT synchronized!
1129 *******************************************************************************/
1131 void classcache_free(void)
1134 classcache_name_entry *entry;
1135 classcache_name_entry *next;
1137 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1138 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1139 next = entry->hashlink;
1140 classcache_free_name_entry(entry);
1144 MFREE(hashtable_classcache.ptr, void*, hashtable_classcache.size);
1145 hashtable_classcache.size = 0;
1146 hashtable_classcache.entries = 0;
1147 hashtable_classcache.ptr = NULL;
1150 /* classcache_add_constraint ***************************************************
1152 Add a loading constraint
1155 a................first initiating loader
1156 b................second initiating loader
1157 classname........class name
1160 true.............everything ok, the constraint has been added,
1161 false............an exception has been thrown.
1163 Note: synchronized with global tablelock
1165 *******************************************************************************/
1167 #if defined(ENABLE_VERIFIER)
1168 bool classcache_add_constraint(classloader_t * a,
1172 classcache_name_entry *en;
1173 classcache_class_entry *clsenA;
1174 classcache_class_entry *clsenB;
1178 #ifdef CLASSCACHE_VERBOSE
1180 log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1181 utf_fprint_printable_ascii_classname(stdout, classname);
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 exceptions_throw_linkageerror("loading constraint violated: ",
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 */
1265 #endif /* defined(ENABLE_VERIFIER) */
1267 /* classcache_add_constraints_for_params ***************************************
1269 Add loading constraints for the parameters and return type of
1273 a................first initiating loader
1274 b................second initiating loader
1275 m................methodinfo
1278 true.............everything ok, the constraints have been added,
1279 false............an exception has been thrown.
1281 Note: synchronized with global tablelock
1283 *******************************************************************************/
1285 #if defined(ENABLE_VERIFIER)
1286 bool classcache_add_constraints_for_params(classloader_t * a,
1294 /* a constraint with a == b is trivially satisfied */
1300 /* get the parsed descriptor */
1306 /* constrain the return type */
1308 if (md->returntype.type == TYPE_ADR) {
1309 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1310 return false; /* exception */
1313 /* constrain each reference type used in the parameters */
1315 td = md->paramtypes;
1318 if (td->type != TYPE_ADR)
1321 if (!classcache_add_constraint(a, b, td->classref->name))
1322 return false; /* exception */
1328 #endif /* defined(ENABLE_VERIFIER) */
1331 /* classcache_number_of_loaded_classes *****************************************
1333 Counts the number of loaded classes and returns it.
1335 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1338 *******************************************************************************/
1340 static s4 classcache_number_of_loaded_classes(void)
1342 classcache_name_entry *en;
1343 classcache_class_entry *clsen;
1347 /* initialize class counter */
1351 for (i = 0; i < hashtable_classcache.size; i++) {
1352 /* iterate over hashlink */
1354 for (en = (classcache_name_entry*) hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1355 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1357 if (en->name->text[0] == '$')
1360 /* iterate over classes with same name */
1362 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1363 /* get only loaded classes */
1365 if (clsen->classobj != NULL)
1375 /* classcache_get_loaded_class_count *******************************************
1377 Counts the number of loaded classes and returns it.
1379 *******************************************************************************/
1381 s4 classcache_get_loaded_class_count(void)
1387 count = classcache_number_of_loaded_classes();
1389 CLASSCACHE_UNLOCK();
1395 /* classcache_get_loaded_classes ***********************************************
1397 Returns an array of all loaded classes as array. The array is
1398 allocaed on the Java heap.
1400 *******************************************************************************/
1402 #if defined(ENABLE_JVMTI)
1403 void classcache_get_loaded_classes(s4 *class_count_ptr,
1404 classinfo ***classes_ptr)
1406 classinfo **classes;
1408 classcache_name_entry *en;
1409 classcache_class_entry *clsen;
1415 /* get the number of loaded classes and allocate the array */
1417 class_count = classcache_number_of_loaded_classes();
1419 classes = GCMNEW(classinfo*, class_count);
1421 /* look in every slot of the hashtable */
1423 for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1424 /* iterate over hashlink */
1426 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1427 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1429 if (en->name->text[0] == '$')
1432 /* iterate over classes with same name */
1434 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1435 /* get only loaded classes */
1437 if (clsen->classobj != NULL) {
1438 classes[j] = clsen->classobj;
1445 /* pass the return values */
1447 *class_count_ptr = class_count;
1448 *classes_ptr = classes;
1450 CLASSCACHE_UNLOCK();
1452 #endif /* defined(ENABLE_JVMTI) */
1455 /* classcache_foreach_loaded_class *********************************************
1457 Calls the given function for each loaded class.
1459 *******************************************************************************/
1461 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1464 classcache_name_entry *en;
1465 classcache_class_entry *clsen;
1470 /* look in every slot of the hashtable */
1472 for (i = 0; i < hashtable_classcache.size; i++) {
1473 /* iterate over hashlink */
1475 for (en = (classcache_name_entry*) hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1476 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1478 if (en->name->text[0] == '$')
1481 /* iterate over classes with same name */
1483 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1484 /* get only loaded classes */
1486 if (clsen->classobj != NULL) {
1487 (*func)(clsen->classobj, data);
1493 CLASSCACHE_UNLOCK();
1497 /*============================================================================*/
1499 /*============================================================================*/
1501 /* classcache_debug_dump *******************************************************
1503 Print the contents of the loaded class cache to a stream
1506 file.............output stream
1507 only.............if != NULL, only print entries for this name
1508 (Currently we print also the rest of the hash chain to
1509 get a feel for the average length of hash chains.)
1511 Note: synchronized with global tablelock
1513 *******************************************************************************/
1516 void classcache_debug_dump(FILE * file,utf *only)
1518 classcache_name_entry *c;
1519 classcache_class_entry *clsen;
1520 classcache_loader_entry *lden;
1525 log_println("=== [loaded class cache] =====================================");
1526 log_println("hash size : %d", (int) hashtable_classcache.size);
1527 log_println("hash entries: %d", (int) hashtable_classcache.entries);
1531 c = classcache_lookup_name(only);
1532 slot = 0; /* avoid compiler warning */
1536 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1537 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1540 for (; c; c = c->hashlink) {
1541 utf_fprint_printable_ascii_classname(file, c->name);
1542 fprintf(file, "\n");
1544 /* iterate over all class entries */
1545 for (clsen = c->classes; clsen; clsen = clsen->next) {
1546 if (clsen->classobj) {
1547 log_println(" loaded %p", (void *) clsen->classobj);
1550 log_println(" unresolved");
1554 log_print(" loaders: ");
1555 for (lden = clsen->loaders; lden; lden = lden->next) {
1556 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1561 log_print(" constraints: ");
1562 for (lden = clsen->constraints; lden; lden = lden->next) {
1563 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1572 fprintf(file, "\n==============================================================\n\n");
1574 CLASSCACHE_UNLOCK();
1577 #if defined(__cplusplus)
1584 * These are local overrides for various environment variables in Emacs.
1585 * Please do not remove this and leave it at the end of the file, where
1586 * Emacs will automagically detect them.
1587 * ---------------------------------------------------------------------
1590 * indent-tabs-mode: t
1594 * vim:noexpandtab:sw=4:ts=4: