1 /* src/vmcore/classcache.c - 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-common.h"
36 #include "toolbox/hashtable.h"
37 #include "toolbox/logging.h"
39 #include "vm/exceptions.h"
41 #include "vmcore/classcache.h"
42 #include "vmcore/options.h"
43 #include "vmcore/utf8.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 /*============================================================================*/
143 /*============================================================================*/
145 /*#define CLASSCACHE_STATS*/
147 #ifdef CLASSCACHE_STATS
148 static int stat_classnames_stored = 0;
149 static int stat_classes_stored = 0;
150 static int stat_trivial_constraints = 0;
151 static int stat_nontriv_constraints = 0;
152 static int stat_nontriv_constraints_both = 0;
153 static int stat_nontriv_constraints_merged = 0;
154 static int stat_nontriv_constraints_one = 0;
155 static int stat_nontriv_constraints_none = 0;
156 static int stat_new_loader_entry = 0;
157 static int stat_merge_class_entries = 0;
158 static int stat_merge_loader_entries = 0;
159 static int stat_lookup = 0;
160 static int stat_lookup_class_entry_checked = 0;
161 static int stat_lookup_loader_checked = 0;
162 static int stat_lookup_name = 0;
163 static int stat_lookup_name_entry = 0;
164 static int stat_lookup_name_notfound = 0;
165 static int stat_lookup_new_name = 0;
166 static int stat_lookup_new_name_entry = 0;
167 static int stat_lookup_new_name_collisions = 0;
168 static int stat_rehash_names = 0;
169 static int stat_rehash_names_collisions = 0;
171 #define CLASSCACHE_COUNT(cnt) (cnt)++
172 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
174 void classcache_print_statistics(FILE *file) {
175 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
176 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
177 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
178 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
179 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
180 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
181 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
182 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
183 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
184 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
185 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
186 fprintf(file,"lookups : %8d\n",stat_lookup);
187 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
188 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
189 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
190 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
191 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
192 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
193 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
194 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
195 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
196 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
199 #define CLASSCACHE_COUNT(cnt)
200 #define CLASSCACHE_COUNTIF(cond,cnt)
203 /*============================================================================*/
204 /* THREAD-SAFE LOCKING */
205 /*============================================================================*/
207 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
208 /* CAUTION: The static functions below are */
209 /* NOT synchronized! */
210 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
212 #if defined(ENABLE_THREADS)
213 # define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
214 # define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
216 # define CLASSCACHE_LOCK()
217 # define CLASSCACHE_UNLOCK()
220 /*============================================================================*/
221 /* GLOBAL VARIABLES */
222 /*============================================================================*/
224 hashtable hashtable_classcache;
226 #if defined(ENABLE_THREADS)
227 static java_object_t *lock_hashtable_classcache;
231 /*============================================================================*/
233 /*============================================================================*/
237 static void classcache_free_class_entry(classcache_class_entry *clsen);
238 static void classcache_remove_class_entry(classcache_name_entry *en,
239 classcache_class_entry *clsen);
241 /* hash function to use */
243 #define CLASSCACHE_HASH utf_full_hashkey
245 /* classcache_init *************************************************************
247 Initialize the class cache
249 Note: NOT synchronized!
251 *******************************************************************************/
253 bool classcache_init(void)
255 TRACESUBSYSTEMINITIALIZATION("classcache_init");
257 /* create the hashtable */
259 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
261 #if defined(ENABLE_THREADS)
262 /* create utf hashtable lock object */
264 lock_hashtable_classcache = NEW(java_object_t);
266 LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
269 /* everything's ok */
274 /* classcache_new_loader_entry *************************************************
276 Create a new classcache_loader_entry struct
277 (internally used helper function)
280 loader...........the ClassLoader object
281 next.............the next classcache_loader_entry
284 the new classcache_loader_entry
286 *******************************************************************************/
288 static classcache_loader_entry * classcache_new_loader_entry(
289 classloader_t * loader,
290 classcache_loader_entry * next)
292 classcache_loader_entry *lden;
294 lden = NEW(classcache_loader_entry);
295 lden->loader = loader;
297 CLASSCACHE_COUNT(stat_new_loader_entry);
302 /* classcache_merge_loaders ****************************************************
304 Merge two lists of loaders into one
305 (internally used helper function)
308 lista............first list (may be NULL)
309 listb............second list (may be NULL)
312 the merged list (may be NULL)
315 The lists given as arguments are destroyed!
317 *******************************************************************************/
319 static classcache_loader_entry * classcache_merge_loaders(
320 classcache_loader_entry * lista,
321 classcache_loader_entry * listb)
323 classcache_loader_entry *result;
324 classcache_loader_entry *ldenA;
325 classcache_loader_entry *ldenB;
326 classcache_loader_entry **chain;
328 CLASSCACHE_COUNT(stat_merge_loader_entries);
330 /* XXX This is a quadratic algorithm. If this ever
331 * becomes a problem, the loader lists should be
332 * stored as sorted lists and merged in linear time. */
337 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
339 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
340 if (ldenB->loader == ldenA->loader)
344 /* this loader is only in lista */
346 chain = &(ldenA->next);
349 /* XXX free the duplicated element */
353 /* concat listb to the result */
359 /* classcache_merge_class_entries **********************************************
361 Merge two `classcache_class_entry`s into one.
362 (internally used helper function)
365 en...............the classcache_name_entry containing both class entries
366 clsenA...........first class entry, will receive the result
367 clsenB...........second class entry
370 Either both entries must have the same classobj, or one of them has
374 clsenB is freed by this function!
376 *******************************************************************************/
378 static void classcache_merge_class_entries(classcache_name_entry *en,
379 classcache_class_entry *clsenA,
380 classcache_class_entry *clsenB)
382 #ifdef CLASSCACHE_VERBOSE
383 char logbuffer[1024];
389 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
391 #ifdef CLASSCACHE_VERBOSE
392 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
393 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
394 if (clsenA->classobj)
395 utf_cat_classname(logbuffer, clsenA->classobj->name);
396 if (clsenB->classobj)
397 utf_cat_classname(logbuffer, clsenB->classobj->name);
398 log_println(logbuffer);
401 CLASSCACHE_COUNT(stat_merge_class_entries);
403 /* clsenB will be merged into clsenA */
404 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
405 clsenB->loaders = NULL; /* these have been freed or reused */
407 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
408 clsenB->constraints);
409 clsenB->constraints = NULL; /* these have been freed or reused */
411 if (!clsenA->classobj)
412 clsenA->classobj = clsenB->classobj;
414 /* remove clsenB from the list of class entries */
415 classcache_remove_class_entry(en, clsenB);
419 /* classcache_lookup_name ******************************************************
421 Lookup a name in the first level of the cache
422 (internally used helper function)
425 name.............the name to look up
428 a pointer to the classcache_name_entry for this name, or
429 null if no entry was found.
431 *******************************************************************************/
433 static classcache_name_entry *classcache_lookup_name(utf *name)
435 classcache_name_entry *c; /* hash table element */
436 u4 key; /* hashkey computed from classname */
437 u4 slot; /* slot in hashtable */
439 CLASSCACHE_COUNT(stat_lookup_name);
441 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
442 slot = key & (hashtable_classcache.size - 1);
443 c = hashtable_classcache.ptr[slot];
445 /* search external hash chain for the entry */
448 /* entry found in hashtable */
449 CLASSCACHE_COUNT(stat_lookup_name_entry);
454 c = c->hashlink; /* next element in external chain */
459 CLASSCACHE_COUNT(stat_lookup_name_notfound);
464 /* classcache_new_name *********************************************************
466 Return a classcache_name_entry for the given name. The entry is created
467 if it is not already in the cache.
468 (internally used helper function)
471 name.............the name to look up / create an entry for
474 a pointer to the classcache_name_entry for this name
476 *******************************************************************************/
478 static classcache_name_entry *classcache_new_name(utf *name)
480 classcache_name_entry *c; /* hash table element */
481 u4 key; /* hashkey computed from classname */
482 u4 slot; /* slot in hashtable */
485 CLASSCACHE_COUNT(stat_lookup_new_name);
487 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
488 slot = key & (hashtable_classcache.size - 1);
489 c = hashtable_classcache.ptr[slot];
491 /* search external hash chain for the entry */
494 /* entry found in hashtable */
495 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
500 c = c->hashlink; /* next element in external chain */
503 /* location in hashtable found, create new entry */
505 c = NEW(classcache_name_entry);
510 /* insert entry into hashtable */
511 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
512 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
513 hashtable_classcache.ptr[slot] = c;
515 /* update number of hashtable-entries */
516 hashtable_classcache.entries++;
517 CLASSCACHE_COUNT(stat_classnames_stored);
519 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
520 /* reorganization of hashtable */
522 classcache_name_entry *c2;
523 hashtable newhash; /* the new hashtable */
525 CLASSCACHE_COUNT(stat_rehash_names);
527 /* create new hashtable, double the size */
529 hashtable_create(&newhash, hashtable_classcache.size * 2);
530 newhash.entries = hashtable_classcache.entries;
532 /* transfer elements to new hashtable */
534 for (i = 0; i < hashtable_classcache.size; i++) {
535 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
537 classcache_name_entry *nextc = c2->hashlink;
539 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
541 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
542 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
543 newhash.ptr[newslot] = c2;
549 /* dispose old table */
551 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
552 hashtable_classcache = newhash;
559 /* classcache_lookup ***********************************************************
561 Lookup a possibly loaded class
564 initloader.......initiating loader for resolving the class name
565 classname........class name to look up
568 The return value is a pointer to the cached class object,
569 or NULL, if the class is not in the cache.
571 Note: synchronized with global tablelock
573 *******************************************************************************/
575 classinfo *classcache_lookup(classloader_t *initloader, utf *classname)
577 classcache_name_entry *en;
578 classcache_class_entry *clsen;
579 classcache_loader_entry *lden;
580 classinfo *cls = NULL;
584 CLASSCACHE_COUNT(stat_lookup);
585 en = classcache_lookup_name(classname);
588 /* iterate over all class entries */
590 for (clsen = en->classes; clsen; clsen = clsen->next) {
591 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
592 /* check if this entry has been loaded by initloader */
594 for (lden = clsen->loaders; lden; lden = lden->next) {
595 CLASSCACHE_COUNT(stat_lookup_loader_checked);
596 if (lden->loader == initloader) {
597 /* found the loaded class entry */
599 assert(clsen->classobj);
600 cls = clsen->classobj;
613 /* classcache_lookup_defined ***************************************************
615 Lookup a class with the given name and defining loader
618 defloader........defining loader
619 classname........class name
622 The return value is a pointer to the cached class object,
623 or NULL, if the class is not in the cache.
625 *******************************************************************************/
627 classinfo *classcache_lookup_defined(classloader_t *defloader, utf *classname)
629 classcache_name_entry *en;
630 classcache_class_entry *clsen;
631 classinfo *cls = NULL;
635 en = classcache_lookup_name(classname);
638 /* iterate over all class entries */
639 for (clsen = en->classes; clsen; clsen = clsen->next) {
640 if (!clsen->classobj)
643 /* check if this entry has been defined by defloader */
644 if (clsen->classobj->classloader == defloader) {
645 cls = clsen->classobj;
657 /* classcache_lookup_defined_or_initiated **************************************
659 Lookup a class that has been defined or initiated by the given loader
662 loader...........defining or initiating loader
663 classname........class name to look up
666 The return value is a pointer to the cached class object,
667 or NULL, if the class is not in the cache.
669 Note: synchronized with global tablelock
671 *******************************************************************************/
673 classinfo *classcache_lookup_defined_or_initiated(classloader_t *loader,
676 classcache_name_entry *en;
677 classcache_class_entry *clsen;
678 classcache_loader_entry *lden;
679 classinfo *cls = NULL;
683 en = classcache_lookup_name(classname);
686 /* iterate over all class entries */
688 for (clsen = en->classes; clsen; clsen = clsen->next) {
690 /* check if this entry has been defined by loader */
691 if (clsen->classobj && clsen->classobj->classloader == loader) {
692 cls = clsen->classobj;
696 /* check if this entry has been initiated by loader */
697 for (lden = clsen->loaders; lden; lden = lden->next) {
698 if (lden->loader == loader) {
699 /* found the loaded class entry */
701 assert(clsen->classobj);
702 cls = clsen->classobj;
715 /* classcache_store ************************************************************
717 Store a loaded class. If a class of the same name has already been stored
718 with the same initiating loader, then the given class CLS is freed (if
719 possible) and the previously stored class is returned.
722 initloader.......initiating loader used to load the class
723 (may be NULL indicating the bootstrap loader)
724 cls..............class object to cache
725 mayfree..........true if CLS may be freed in case another class is
729 cls..............everything ok, the class was stored in the cache,
730 other classinfo..another class with the same (initloader,name) has been
731 stored earlier. CLS has been freed[1] and the earlier
732 stored class is returned.
733 NULL.............an exception has been thrown.
735 Note: synchronized with global tablelock
737 [1]...in case MAYFREE is true
739 *******************************************************************************/
741 classinfo *classcache_store(classloader_t *initloader, classinfo *cls,
744 classcache_name_entry *en;
745 classcache_class_entry *clsen;
746 classcache_class_entry *clsenB;
747 classcache_loader_entry *lden;
748 #ifdef CLASSCACHE_VERBOSE
749 char logbuffer[1024];
753 assert(cls->state & CLASS_LOADED);
757 #ifdef CLASSCACHE_VERBOSE
758 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
759 utf_cat_classname(logbuffer, cls->name);
760 strcat(logbuffer,")");
761 log_println(logbuffer);
764 en = classcache_new_name(cls->name);
768 /* iterate over all class entries */
769 for (clsen = en->classes; clsen; clsen = clsen->next) {
771 /* check if this entry has already been loaded by initloader */
772 for (lden = clsen->loaders; lden; lden = lden->next) {
773 if (lden->loader == initloader) {
774 if (clsen->classobj != cls) {
775 /* A class with the same (initloader,name) pair has been stored already. */
776 /* We free the given class and return the earlier one. */
777 #ifdef CLASSCACHE_VERBOSE
778 log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
780 assert(clsen->classobj);
783 cls = clsen->classobj;
789 /* {This entry has not been resolved with initloader} */
791 /* check if initloader is constrained to this entry */
792 for (lden = clsen->constraints; lden; lden = lden->next) {
793 if (lden->loader == initloader) {
794 /* we have to use this entry. check if it has been resolved */
795 if (clsen->classobj) {
796 /* check if is has already been resolved to another class */
797 if (clsen->classobj != cls) {
798 /* a loading constraint is violated */
799 exceptions_throw_linkageerror("loading constraint violated: ", cls);
800 goto return_exception;
803 /* record initloader as initiating loader */
804 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
808 /* {this is the first resolution for this entry} */
809 /* record initloader as initiating loader */
810 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
812 /* maybe we can merge this entry with another one */
813 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
814 /* we dont want the entry that we have already */
815 if (clsenB->classobj == cls) {
816 /* this entry has the same classobj. let's merge them */
817 classcache_merge_class_entries(en,clsen,clsenB);
822 /* record the loaded class object */
823 clsen->classobj = cls;
824 CLASSCACHE_COUNT(stat_classes_stored);
833 /* {There is no class entry containing initloader as initiating
834 * or constrained loader.} */
836 /* we look for a class entry with the same classobj we want to store */
837 for (clsen = en->classes; clsen; clsen = clsen->next) {
838 if (clsen->classobj == cls) {
839 /* this entry is about the same classobj. let's use it */
840 /* check if this entry has already been loaded by initloader */
841 for (lden = clsen->loaders; lden; lden = lden->next) {
842 if (lden->loader == initloader)
845 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
850 /* create a new class entry for this class object with */
851 /* initiating loader initloader */
853 clsen = NEW(classcache_class_entry);
854 clsen->classobj = cls;
855 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
856 clsen->constraints = NULL;
858 clsen->next = en->classes;
860 CLASSCACHE_COUNT(stat_classes_stored);
863 #ifdef CLASSCACHE_VERBOSE
864 classcache_debug_dump(stdout,cls->name);
871 return NULL; /* exception */
874 /* classcache_store_unique *****************************************************
876 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
877 aroung classcache_store that throws an exception if a class with the same
878 name has already been loaded by the bootstrap loader.
880 This function is used to register a few special classes during startup.
881 It should not be used otherwise.
884 cls..............class object to cache
887 true.............everything ok, the class was stored.
888 false............an exception has been thrown.
890 Note: synchronized with global tablelock
892 *******************************************************************************/
894 bool classcache_store_unique(classinfo *cls)
898 result = classcache_store(NULL,cls,false);
903 exceptions_throw_internalerror("class already stored in the class cache");
910 /* classcache_store_defined ****************************************************
912 Store a loaded class after it has been defined. If the class has already
913 been defined by the same defining loader in another thread, free the given
914 class and returned the one which has been defined earlier.
917 cls..............class object to store. classloader must be set
918 (classloader may be NULL, for bootloader)
921 cls..............everything ok, the class was stored the cache,
922 other classinfo..the class had already been defined, CLS was freed, the
923 class which was defined earlier is returned,
924 NULL.............an exception has been thrown.
926 *******************************************************************************/
928 classinfo *classcache_store_defined(classinfo *cls)
930 classcache_name_entry *en;
931 classcache_class_entry *clsen;
932 #ifdef CLASSCACHE_VERBOSE
933 char logbuffer[1024];
937 assert(cls->state & CLASS_LOADED);
941 #ifdef CLASSCACHE_VERBOSE
942 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
943 utf_cat_classname(logbuffer, cls->name);
944 strcat(logbuffer,")");
945 log_println(logbuffer);
948 en = classcache_new_name(cls->name);
952 /* iterate over all class entries */
953 for (clsen = en->classes; clsen; clsen = clsen->next) {
955 /* check if this class has been defined by the same classloader */
956 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
957 /* we found an earlier definition, delete the newer one */
958 /* (if it is a different classinfo) */
959 if (clsen->classobj != cls) {
960 #ifdef CLASSCACHE_VERBOSE
961 log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
964 cls = clsen->classobj;
970 /* create a new class entry for this class object */
971 /* the list of initiating loaders is empty at this point */
973 clsen = NEW(classcache_class_entry);
974 clsen->classobj = cls;
975 clsen->loaders = NULL;
976 clsen->constraints = NULL;
978 clsen->next = en->classes;
980 CLASSCACHE_COUNT(stat_classes_stored);
983 #ifdef CLASSCACHE_VERBOSE
984 classcache_debug_dump(stdout,cls->name);
990 /* classcache_find_loader ******************************************************
992 Find the class entry loaded by or constrained to a given loader
993 (internally used helper function)
996 entry............the classcache_name_entry
997 loader...........the loader to look for
1000 the classcache_class_entry for the given loader, or
1001 NULL if no entry was found
1003 *******************************************************************************/
1005 static classcache_class_entry * classcache_find_loader(
1006 classcache_name_entry * entry,
1007 classloader_t * loader)
1009 classcache_class_entry *clsen;
1010 classcache_loader_entry *lden;
1014 /* iterate over all class entries */
1015 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1017 /* check if this entry has already been loaded by initloader */
1018 for (lden = clsen->loaders; lden; lden = lden->next) {
1019 if (lden->loader == loader)
1020 return clsen; /* found */
1023 /* check if loader is constrained to this entry */
1024 for (lden = clsen->constraints; lden; lden = lden->next) {
1025 if (lden->loader == loader)
1026 return clsen; /* found */
1034 /* classcache_free_class_entry *************************************************
1036 Free the memory used by a class entry
1039 clsen............the classcache_class_entry to free
1041 *******************************************************************************/
1043 static void classcache_free_class_entry(classcache_class_entry * clsen)
1045 classcache_loader_entry *lden;
1046 classcache_loader_entry *next;
1050 for (lden = clsen->loaders; lden; lden = next) {
1052 FREE(lden, classcache_loader_entry);
1054 for (lden = clsen->constraints; lden; lden = next) {
1056 FREE(lden, classcache_loader_entry);
1059 FREE(clsen, classcache_class_entry);
1062 /* classcache_remove_class_entry ***********************************************
1064 Remove a classcache_class_entry from the list of possible resolution of
1066 (internally used helper function)
1069 entry............the classcache_name_entry
1070 clsen............the classcache_class_entry to remove
1072 *******************************************************************************/
1074 static void classcache_remove_class_entry(classcache_name_entry * entry,
1075 classcache_class_entry * clsen)
1077 classcache_class_entry **chain;
1082 chain = &(entry->classes);
1084 if (*chain == clsen) {
1085 *chain = clsen->next;
1086 classcache_free_class_entry(clsen);
1089 chain = &((*chain)->next);
1093 /* classcache_free_name_entry **************************************************
1095 Free the memory used by a name entry
1098 entry............the classcache_name_entry to free
1100 *******************************************************************************/
1102 static void classcache_free_name_entry(classcache_name_entry * entry)
1104 classcache_class_entry *clsen;
1105 classcache_class_entry *next;
1109 for (clsen = entry->classes; clsen; clsen = next) {
1111 classcache_free_class_entry(clsen);
1114 FREE(entry, classcache_name_entry);
1117 /* classcache_free *************************************************************
1119 Free the memory used by the class cache
1122 The class cache may not be used any more after this call, except
1123 when it is reinitialized with classcache_init.
1125 Note: NOT synchronized!
1127 *******************************************************************************/
1129 void classcache_free(void)
1132 classcache_name_entry *entry;
1133 classcache_name_entry *next;
1135 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1136 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1137 next = entry->hashlink;
1138 classcache_free_name_entry(entry);
1142 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1143 hashtable_classcache.size = 0;
1144 hashtable_classcache.entries = 0;
1145 hashtable_classcache.ptr = NULL;
1148 /* classcache_add_constraint ***************************************************
1150 Add a loading constraint
1153 a................first initiating loader
1154 b................second initiating loader
1155 classname........class name
1158 true.............everything ok, the constraint has been added,
1159 false............an exception has been thrown.
1161 Note: synchronized with global tablelock
1163 *******************************************************************************/
1165 #if defined(ENABLE_VERIFIER)
1166 bool classcache_add_constraint(classloader_t * a,
1170 classcache_name_entry *en;
1171 classcache_class_entry *clsenA;
1172 classcache_class_entry *clsenB;
1176 #ifdef CLASSCACHE_VERBOSE
1178 log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1179 utf_fprint_printable_ascii_classname(stdout, classname);
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 exceptions_throw_linkageerror("loading constraint violated: ",
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 */
1263 #endif /* defined(ENABLE_VERIFIER) */
1265 /* classcache_add_constraints_for_params ***************************************
1267 Add loading constraints for the parameters and return type of
1271 a................first initiating loader
1272 b................second initiating loader
1273 m................methodinfo
1276 true.............everything ok, the constraints have been added,
1277 false............an exception has been thrown.
1279 Note: synchronized with global tablelock
1281 *******************************************************************************/
1283 #if defined(ENABLE_VERIFIER)
1284 bool classcache_add_constraints_for_params(classloader_t * a,
1292 /* a constraint with a == b is trivially satisfied */
1298 /* get the parsed descriptor */
1304 /* constrain the return type */
1306 if (md->returntype.type == TYPE_ADR) {
1307 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1308 return false; /* exception */
1311 /* constrain each reference type used in the parameters */
1313 td = md->paramtypes;
1316 if (td->type != TYPE_ADR)
1319 if (!classcache_add_constraint(a, b, td->classref->name))
1320 return false; /* exception */
1326 #endif /* defined(ENABLE_VERIFIER) */
1329 /* classcache_number_of_loaded_classes *****************************************
1331 Counts the number of loaded classes and returns it.
1333 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1336 *******************************************************************************/
1338 static s4 classcache_number_of_loaded_classes(void)
1340 classcache_name_entry *en;
1341 classcache_class_entry *clsen;
1345 /* initialize class counter */
1349 for (i = 0; i < hashtable_classcache.size; i++) {
1350 /* iterate over hashlink */
1352 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1353 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1355 if (en->name->text[0] == '$')
1358 /* iterate over classes with same name */
1360 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1361 /* get only loaded classes */
1363 if (clsen->classobj != NULL)
1373 /* classcache_get_loaded_class_count *******************************************
1375 Counts the number of loaded classes and returns it.
1377 *******************************************************************************/
1379 s4 classcache_get_loaded_class_count(void)
1385 count = classcache_number_of_loaded_classes();
1387 CLASSCACHE_UNLOCK();
1393 /* classcache_get_loaded_classes ***********************************************
1395 Returns an array of all loaded classes as array. The array is
1396 allocaed on the Java heap.
1398 *******************************************************************************/
1400 #if defined(ENABLE_JVMTI)
1401 void classcache_get_loaded_classes(s4 *class_count_ptr,
1402 classinfo ***classes_ptr)
1404 classinfo **classes;
1406 classcache_name_entry *en;
1407 classcache_class_entry *clsen;
1413 /* get the number of loaded classes and allocate the array */
1415 class_count = classcache_number_of_loaded_classes();
1417 classes = GCMNEW(classinfo*, class_count);
1419 /* look in every slot of the hashtable */
1421 for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1422 /* iterate over hashlink */
1424 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1425 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1427 if (en->name->text[0] == '$')
1430 /* iterate over classes with same name */
1432 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1433 /* get only loaded classes */
1435 if (clsen->classobj != NULL) {
1436 classes[j] = clsen->classobj;
1443 /* pass the return values */
1445 *class_count_ptr = class_count;
1446 *classes_ptr = classes;
1448 CLASSCACHE_UNLOCK();
1450 #endif /* defined(ENABLE_JVMTI) */
1453 /* classcache_foreach_loaded_class *********************************************
1455 Calls the given function for each loaded class.
1457 *******************************************************************************/
1459 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1462 classcache_name_entry *en;
1463 classcache_class_entry *clsen;
1468 /* look in every slot of the hashtable */
1470 for (i = 0; i < hashtable_classcache.size; i++) {
1471 /* iterate over hashlink */
1473 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1474 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1476 if (en->name->text[0] == '$')
1479 /* iterate over classes with same name */
1481 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1482 /* get only loaded classes */
1484 if (clsen->classobj != NULL) {
1485 (*func)(clsen->classobj, data);
1491 CLASSCACHE_UNLOCK();
1495 /*============================================================================*/
1497 /*============================================================================*/
1499 /* classcache_debug_dump *******************************************************
1501 Print the contents of the loaded class cache to a stream
1504 file.............output stream
1505 only.............if != NULL, only print entries for this name
1506 (Currently we print also the rest of the hash chain to
1507 get a feel for the average length of hash chains.)
1509 Note: synchronized with global tablelock
1511 *******************************************************************************/
1514 void classcache_debug_dump(FILE * file,utf *only)
1516 classcache_name_entry *c;
1517 classcache_class_entry *clsen;
1518 classcache_loader_entry *lden;
1523 log_println("=== [loaded class cache] =====================================");
1524 log_println("hash size : %d", (int) hashtable_classcache.size);
1525 log_println("hash entries: %d", (int) hashtable_classcache.entries);
1529 c = classcache_lookup_name(only);
1530 slot = 0; /* avoid compiler warning */
1534 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1535 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1538 for (; c; c = c->hashlink) {
1539 utf_fprint_printable_ascii_classname(file, c->name);
1540 fprintf(file, "\n");
1542 /* iterate over all class entries */
1543 for (clsen = c->classes; clsen; clsen = clsen->next) {
1544 if (clsen->classobj) {
1545 log_println(" loaded %p", (void *) clsen->classobj);
1548 log_println(" unresolved");
1552 log_print(" loaders: ");
1553 for (lden = clsen->loaders; lden; lden = lden->next) {
1554 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1559 log_print(" constraints: ");
1560 for (lden = clsen->constraints; lden; lden = lden->next) {
1561 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1570 fprintf(file, "\n==============================================================\n\n");
1572 CLASSCACHE_UNLOCK();
1577 * These are local overrides for various environment variables in Emacs.
1578 * Please do not remove this and leave it at the end of the file, where
1579 * Emacs will automagically detect them.
1580 * ---------------------------------------------------------------------
1583 * indent-tabs-mode: t
1587 * vim:noexpandtab:sw=4:ts=4: