1 /* src/vm/classcache.c - loaded class cache and loading constraints
3 Copyright (C) 1996-2005, 2006, 2007 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
30 $Id: classcache.c 6286 2007-01-10 10:03:38Z twisti $
40 #include "mm/memory.h"
42 #if defined(ENABLE_THREADS)
43 # include "threads/native/lock.h"
46 #include "vm/classcache.h"
47 #include "vm/exceptions.h"
48 #include "vm/hashtable.h"
49 #include "vm/stringlocal.h"
53 /*************************************************************************
57 The classcache has two functions:
59 1) caching the resolution of class references
60 2) storing and checking loading constraints
62 We will use the following terms in this description:
64 N a class name: a utf string
65 (N,L) a class reference with initiating loader L and class name N
66 C a class (object): the result of resolving a reference (N,L)
67 We will write resultion as
69 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
70 resolve to the same class C. So (N,L1,L2) means
73 The functions of the classcache require:
75 1) a mapping (N,L) |--> C for looking up prior resolution results.
76 2) storing the current set of loading constraints { (N,L1,L2) }
78 These functions can be rearranged like that:
80 a mapping N |--> (a mapping L |--> C or NULL,
81 a set of constraints {(L1,L2)})
83 Thus we can treat the mapping and constraints for each name N
84 separately. The implementation does this by keeping a hash table
85 mapping a name N to a `classcache_name_entry` which contains all
86 info with respect to N.
88 For a class name N we can define an equivalence relation ~N~ on
91 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
93 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
95 Also, if two references (N,L1) and (N,L2) resolve to the same class C
96 we have L1 ~N~ L2 because class loaders are required to return
97 consistent resolutions for a name N [XXX].
99 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
101 Cx...is a class C or NULL
102 IL...is the set of initiating loaders
103 CL...is the set of constrained loaders
105 Such a tuple is called `classcache_class_entry` in the source code.
107 The following holds for each tuple (Cx,IL,CL):
109 . (Cx is NULL) implies IL = {}.
111 . If Cx is a class, IL is the set of loaders that have been
112 recorded as initiating loaders for Cx. IL may be the
113 empty set {} in case Cx has already been defined but no
114 initiating loader has been recorded, yet.
116 . (IL u CL) is a subset of an equivalence class of ~N~.
118 (This means that all loaders in IL and CL must resolve
119 the name N to the same class.)
121 The following holds for the set of tuples { (Cx,IL,CL) }:
123 . For a given class C there is at most one tuple with Cx = C
124 in the set. (There may be an arbitrary number of tuples
125 with Cx = NULL, however.)
127 . For a given loader L there is at most one tuple with
130 The implementation stores sets of loaders as linked lists of
131 `classcache_loader_entry`s.
133 Comments about manipulating the classcache can be found in the
134 individual functions below.
136 *************************************************************************/
139 /* initial number of slots in the classcache hash table */
140 #define CLASSCACHE_INIT_SIZE 2048
142 /*============================================================================*/
144 /*============================================================================*/
146 /*#define CLASSCACHE_VERBOSE*/
148 /*============================================================================*/
150 /*============================================================================*/
152 /*#define CLASSCACHE_STATS*/
154 #ifdef CLASSCACHE_STATS
155 static int stat_classnames_stored = 0;
156 static int stat_classes_stored = 0;
157 static int stat_trivial_constraints = 0;
158 static int stat_nontriv_constraints = 0;
159 static int stat_nontriv_constraints_both = 0;
160 static int stat_nontriv_constraints_merged = 0;
161 static int stat_nontriv_constraints_one = 0;
162 static int stat_nontriv_constraints_none = 0;
163 static int stat_new_loader_entry = 0;
164 static int stat_merge_class_entries = 0;
165 static int stat_merge_loader_entries = 0;
166 static int stat_lookup = 0;
167 static int stat_lookup_class_entry_checked = 0;
168 static int stat_lookup_loader_checked = 0;
169 static int stat_lookup_name = 0;
170 static int stat_lookup_name_entry = 0;
171 static int stat_lookup_name_notfound = 0;
172 static int stat_lookup_new_name = 0;
173 static int stat_lookup_new_name_entry = 0;
174 static int stat_lookup_new_name_collisions = 0;
175 static int stat_rehash_names = 0;
176 static int stat_rehash_names_collisions = 0;
178 #define CLASSCACHE_COUNT(cnt) (cnt)++
179 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
181 void classcache_print_statistics(FILE *file) {
182 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
183 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
184 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
185 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
186 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
187 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
188 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
189 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
190 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
191 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
192 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
193 fprintf(file,"lookups : %8d\n",stat_lookup);
194 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
195 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
196 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
197 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
198 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
199 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
200 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
201 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
202 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
203 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
206 #define CLASSCACHE_COUNT(cnt)
207 #define CLASSCACHE_COUNTIF(cond,cnt)
210 /*============================================================================*/
211 /* THREAD-SAFE LOCKING */
212 /*============================================================================*/
214 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
215 /* CAUTION: The static functions below are */
216 /* NOT synchronized! */
217 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
219 #if defined(ENABLE_THREADS)
220 # define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
221 # define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
223 # define CLASSCACHE_LOCK()
224 # define CLASSCACHE_UNLOCK()
227 /*============================================================================*/
228 /* GLOBAL VARIABLES */
229 /*============================================================================*/
231 hashtable hashtable_classcache;
233 #if defined(ENABLE_THREADS)
234 static java_objectheader *lock_hashtable_classcache;
238 /*============================================================================*/
240 /*============================================================================*/
244 static void classcache_free_class_entry(classcache_class_entry *clsen);
245 static void classcache_remove_class_entry(classcache_name_entry *en,
246 classcache_class_entry *clsen);
248 /* hash function to use */
250 #define CLASSCACHE_HASH utf_full_hashkey
252 /* classcache_init *************************************************************
254 Initialize the class cache
256 Note: NOT synchronized!
258 *******************************************************************************/
260 bool classcache_init(void)
262 /* create the hashtable */
264 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
266 #if defined(ENABLE_THREADS)
267 /* create utf hashtable lock object */
269 lock_hashtable_classcache = NEW(java_objectheader);
271 lock_init_object_lock(lock_hashtable_classcache);
274 /* everything's ok */
279 /* classcache_new_loader_entry *************************************************
281 Create a new classcache_loader_entry struct
282 (internally used helper function)
285 loader...........the ClassLoader object
286 next.............the next classcache_loader_entry
289 the new classcache_loader_entry
291 *******************************************************************************/
293 static classcache_loader_entry * classcache_new_loader_entry(
294 classloader * loader,
295 classcache_loader_entry * next)
297 classcache_loader_entry *lden;
299 lden = NEW(classcache_loader_entry);
300 lden->loader = loader;
302 CLASSCACHE_COUNT(stat_new_loader_entry);
307 /* classcache_merge_loaders ****************************************************
309 Merge two lists of loaders into one
310 (internally used helper function)
313 lista............first list (may be NULL)
314 listb............second list (may be NULL)
317 the merged list (may be NULL)
320 The lists given as arguments are destroyed!
322 *******************************************************************************/
324 static classcache_loader_entry * classcache_merge_loaders(
325 classcache_loader_entry * lista,
326 classcache_loader_entry * listb)
328 classcache_loader_entry *result;
329 classcache_loader_entry *ldenA;
330 classcache_loader_entry *ldenB;
331 classcache_loader_entry **chain;
333 CLASSCACHE_COUNT(stat_merge_loader_entries);
335 /* XXX This is a quadratic algorithm. If this ever
336 * becomes a problem, the loader lists should be
337 * stored as sorted lists and merged in linear time. */
342 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
344 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
345 if (ldenB->loader == ldenA->loader)
349 /* this loader is only in lista */
351 chain = &(ldenA->next);
354 /* XXX free the duplicated element */
358 /* concat listb to the result */
364 /* classcache_merge_class_entries **********************************************
366 Merge two `classcache_class_entry`s into one.
367 (internally used helper function)
370 en...............the classcache_name_entry containing both class entries
371 clsenA...........first class entry, will receive the result
372 clsenB...........second class entry
375 Either both entries must have the same classobj, or one of them has
379 clsenB is freed by this function!
381 *******************************************************************************/
383 static void classcache_merge_class_entries(classcache_name_entry *en,
384 classcache_class_entry *clsenA,
385 classcache_class_entry *clsenB)
387 #ifdef CLASSCACHE_VERBOSE
388 char logbuffer[1024];
394 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
396 #ifdef CLASSCACHE_VERBOSE
397 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
398 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
399 if (clsenA->classobj)
400 utf_cat_classname(logbuffer, clsenA->classobj->name);
401 if (clsenB->classobj)
402 utf_cat_classname(logbuffer, clsenB->classobj->name);
406 CLASSCACHE_COUNT(stat_merge_class_entries);
408 /* clsenB will be merged into clsenA */
409 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
410 clsenB->loaders = NULL; /* these have been freed or reused */
412 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
413 clsenB->constraints);
414 clsenB->constraints = NULL; /* these have been freed or reused */
416 if (!clsenA->classobj)
417 clsenA->classobj = clsenB->classobj;
419 /* remove clsenB from the list of class entries */
420 classcache_remove_class_entry(en, clsenB);
424 /* classcache_lookup_name ******************************************************
426 Lookup a name in the first level of the cache
427 (internally used helper function)
430 name.............the name to look up
433 a pointer to the classcache_name_entry for this name, or
434 null if no entry was found.
436 *******************************************************************************/
438 static classcache_name_entry *classcache_lookup_name(utf *name)
440 classcache_name_entry *c; /* hash table element */
441 u4 key; /* hashkey computed from classname */
442 u4 slot; /* slot in hashtable */
444 CLASSCACHE_COUNT(stat_lookup_name);
446 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
447 slot = key & (hashtable_classcache.size - 1);
448 c = hashtable_classcache.ptr[slot];
450 /* search external hash chain for the entry */
453 /* entry found in hashtable */
454 CLASSCACHE_COUNT(stat_lookup_name_entry);
459 c = c->hashlink; /* next element in external chain */
464 CLASSCACHE_COUNT(stat_lookup_name_notfound);
469 /* classcache_new_name *********************************************************
471 Return a classcache_name_entry for the given name. The entry is created
472 if it is not already in the cache.
473 (internally used helper function)
476 name.............the name to look up / create an entry for
479 a pointer to the classcache_name_entry for this name
481 *******************************************************************************/
483 static classcache_name_entry *classcache_new_name(utf *name)
485 classcache_name_entry *c; /* hash table element */
486 u4 key; /* hashkey computed from classname */
487 u4 slot; /* slot in hashtable */
490 CLASSCACHE_COUNT(stat_lookup_new_name);
492 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
493 slot = key & (hashtable_classcache.size - 1);
494 c = hashtable_classcache.ptr[slot];
496 /* search external hash chain for the entry */
499 /* entry found in hashtable */
500 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
505 c = c->hashlink; /* next element in external chain */
508 /* location in hashtable found, create new entry */
510 c = NEW(classcache_name_entry);
515 /* insert entry into hashtable */
516 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
517 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
518 hashtable_classcache.ptr[slot] = c;
520 /* update number of hashtable-entries */
521 hashtable_classcache.entries++;
522 CLASSCACHE_COUNT(stat_classnames_stored);
524 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
525 /* reorganization of hashtable */
527 classcache_name_entry *c2;
528 hashtable newhash; /* the new hashtable */
530 CLASSCACHE_COUNT(stat_rehash_names);
532 /* create new hashtable, double the size */
534 hashtable_create(&newhash, hashtable_classcache.size * 2);
535 newhash.entries = hashtable_classcache.entries;
537 /* transfer elements to new hashtable */
539 for (i = 0; i < hashtable_classcache.size; i++) {
540 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
542 classcache_name_entry *nextc = c2->hashlink;
544 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
546 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
547 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
548 newhash.ptr[newslot] = c2;
554 /* dispose old table */
556 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
557 hashtable_classcache = newhash;
564 /* classcache_lookup ***********************************************************
566 Lookup a possibly loaded class
569 initloader.......initiating loader for resolving the class name
570 classname........class name to look up
573 The return value is a pointer to the cached class object,
574 or NULL, if the class is not in the cache.
576 Note: synchronized with global tablelock
578 *******************************************************************************/
580 classinfo *classcache_lookup(classloader *initloader, utf *classname)
582 classcache_name_entry *en;
583 classcache_class_entry *clsen;
584 classcache_loader_entry *lden;
585 classinfo *cls = NULL;
589 CLASSCACHE_COUNT(stat_lookup);
590 en = classcache_lookup_name(classname);
593 /* iterate over all class entries */
595 for (clsen = en->classes; clsen; clsen = clsen->next) {
596 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
597 /* check if this entry has been loaded by initloader */
599 for (lden = clsen->loaders; lden; lden = lden->next) {
600 CLASSCACHE_COUNT(stat_lookup_loader_checked);
601 if (lden->loader == initloader) {
602 /* found the loaded class entry */
604 assert(clsen->classobj);
605 cls = clsen->classobj;
618 /* classcache_lookup_defined ***************************************************
620 Lookup a class with the given name and defining loader
623 defloader........defining loader
624 classname........class name
627 The return value is a pointer to the cached class object,
628 or NULL, if the class is not in the cache.
630 *******************************************************************************/
632 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
634 classcache_name_entry *en;
635 classcache_class_entry *clsen;
636 classinfo *cls = NULL;
640 en = classcache_lookup_name(classname);
643 /* iterate over all class entries */
644 for (clsen = en->classes; clsen; clsen = clsen->next) {
645 if (!clsen->classobj)
648 /* check if this entry has been defined by defloader */
649 if (clsen->classobj->classloader == defloader) {
650 cls = clsen->classobj;
662 /* classcache_lookup_defined_or_initiated **************************************
664 Lookup a class that has been defined or initiated by the given loader
667 loader...........defining or initiating loader
668 classname........class name to look up
671 The return value is a pointer to the cached class object,
672 or NULL, if the class is not in the cache.
674 Note: synchronized with global tablelock
676 *******************************************************************************/
678 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
681 classcache_name_entry *en;
682 classcache_class_entry *clsen;
683 classcache_loader_entry *lden;
684 classinfo *cls = NULL;
688 en = classcache_lookup_name(classname);
691 /* iterate over all class entries */
693 for (clsen = en->classes; clsen; clsen = clsen->next) {
695 /* check if this entry has been defined by loader */
696 if (clsen->classobj && clsen->classobj->classloader == loader) {
697 cls = clsen->classobj;
701 /* check if this entry has been initiated by loader */
702 for (lden = clsen->loaders; lden; lden = lden->next) {
703 if (lden->loader == loader) {
704 /* found the loaded class entry */
706 assert(clsen->classobj);
707 cls = clsen->classobj;
720 /* classcache_store ************************************************************
722 Store a loaded class. If a class of the same name has already been stored
723 with the same initiating loader, then the given class CLS is freed (if
724 possible) and the previously stored class is returned.
727 initloader.......initiating loader used to load the class
728 (may be NULL indicating the bootstrap loader)
729 cls..............class object to cache
730 mayfree..........true if CLS may be freed in case another class is
734 cls..............everything ok, the class was stored in the cache,
735 other classinfo..another class with the same (initloader,name) has been
736 stored earlier. CLS has been freed[1] and the earlier
737 stored class is returned.
738 NULL.............an exception has been thrown.
740 Note: synchronized with global tablelock
742 [1]...in case MAYFREE is true
744 *******************************************************************************/
746 classinfo *classcache_store(classloader *initloader, classinfo *cls,
749 classcache_name_entry *en;
750 classcache_class_entry *clsen;
751 classcache_class_entry *clsenB;
752 classcache_loader_entry *lden;
753 #ifdef CLASSCACHE_VERBOSE
754 char logbuffer[1024];
758 assert(cls->state & CLASS_LOADED);
762 #ifdef CLASSCACHE_VERBOSE
763 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
764 utf_cat_classname(logbuffer, cls->name);
765 strcat(logbuffer,")");
769 en = classcache_new_name(cls->name);
773 /* iterate over all class entries */
774 for (clsen = en->classes; clsen; clsen = clsen->next) {
776 /* check if this entry has already been loaded by initloader */
777 for (lden = clsen->loaders; lden; lden = lden->next) {
778 if (lden->loader == initloader) {
779 if (clsen->classobj != cls) {
780 /* A class with the same (initloader,name) pair has been stored already. */
781 /* We free the given class and return the earlier one. */
782 #ifdef CLASSCACHE_VERBOSE
783 dolog("replacing %p with earlier loaded class %p",cls,clsen->classobj);
785 assert(clsen->classobj);
788 cls = clsen->classobj;
794 /* {This entry has not been resolved with initloader} */
796 /* check if initloader is constrained to this entry */
797 for (lden = clsen->constraints; lden; lden = lden->next) {
798 if (lden->loader == initloader) {
799 /* we have to use this entry. check if it has been resolved */
800 if (clsen->classobj) {
801 /* check if is has already been resolved to another class */
802 if (clsen->classobj != cls) {
803 /* a loading constraint is violated */
804 *exceptionptr = exceptions_new_linkageerror(
805 "loading constraint violated: ",cls);
806 goto return_exception;
809 /* record initloader as initiating loader */
810 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
814 /* {this is the first resolution for this entry} */
815 /* record initloader as initiating loader */
816 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
818 /* maybe we can merge this entry with another one */
819 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
820 /* we dont want the entry that we have already */
821 if (clsenB->classobj == cls) {
822 /* this entry has the same classobj. let's merge them */
823 classcache_merge_class_entries(en,clsen,clsenB);
828 /* record the loaded class object */
829 clsen->classobj = cls;
830 CLASSCACHE_COUNT(stat_classes_stored);
839 /* {There is no class entry containing initloader as initiating
840 * or constrained loader.} */
842 /* we look for a class entry with the same classobj we want to store */
843 for (clsen = en->classes; clsen; clsen = clsen->next) {
844 if (clsen->classobj == cls) {
845 /* this entry is about the same classobj. let's use it */
846 /* check if this entry has already been loaded by initloader */
847 for (lden = clsen->loaders; lden; lden = lden->next) {
848 if (lden->loader == initloader)
851 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
856 /* create a new class entry for this class object with */
857 /* initiating loader initloader */
859 clsen = NEW(classcache_class_entry);
860 clsen->classobj = cls;
861 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
862 clsen->constraints = NULL;
864 clsen->next = en->classes;
866 CLASSCACHE_COUNT(stat_classes_stored);
869 #ifdef CLASSCACHE_VERBOSE
870 classcache_debug_dump(stderr,cls->name);
877 return NULL; /* exception */
880 /* classcache_store_unique *****************************************************
882 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
883 aroung classcache_store that throws an exception if a class with the same
884 name has already been loaded by the bootstrap loader.
886 This function is used to register a few special classes during startup.
887 It should not be used otherwise.
890 cls..............class object to cache
893 true.............everything ok, the class was stored.
894 false............an exception has been thrown.
896 Note: synchronized with global tablelock
898 *******************************************************************************/
900 bool classcache_store_unique(classinfo *cls)
904 result = classcache_store(NULL,cls,false);
909 exceptions_throw_internalerror("class already stored in the class cache");
916 /* classcache_store_defined ****************************************************
918 Store a loaded class after it has been defined. If the class has already
919 been defined by the same defining loader in another thread, free the given
920 class and returned the one which has been defined earlier.
923 cls..............class object to store. classloader must be set
924 (classloader may be NULL, for bootloader)
927 cls..............everything ok, the class was stored the cache,
928 other classinfo..the class had already been defined, CLS was freed, the
929 class which was defined earlier is returned,
930 NULL.............an exception has been thrown.
932 *******************************************************************************/
934 classinfo *classcache_store_defined(classinfo *cls)
936 classcache_name_entry *en;
937 classcache_class_entry *clsen;
938 #ifdef CLASSCACHE_VERBOSE
939 char logbuffer[1024];
943 assert(cls->state & CLASS_LOADED);
947 #ifdef CLASSCACHE_VERBOSE
948 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
949 utf_cat_classname(logbuffer, cls->name);
950 strcat(logbuffer,")");
954 en = classcache_new_name(cls->name);
958 /* iterate over all class entries */
959 for (clsen = en->classes; clsen; clsen = clsen->next) {
961 /* check if this class has been defined by the same classloader */
962 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
963 /* we found an earlier definition, delete the newer one */
964 /* (if it is a different classinfo) */
965 if (clsen->classobj != cls) {
966 #ifdef CLASSCACHE_VERBOSE
967 dolog("replacing %p with earlier defined class %p",cls,clsen->classobj);
970 cls = clsen->classobj;
976 /* create a new class entry for this class object */
977 /* the list of initiating loaders is empty at this point */
979 clsen = NEW(classcache_class_entry);
980 clsen->classobj = cls;
981 clsen->loaders = NULL;
982 clsen->constraints = NULL;
984 clsen->next = en->classes;
986 CLASSCACHE_COUNT(stat_classes_stored);
989 #ifdef CLASSCACHE_VERBOSE
990 classcache_debug_dump(stderr,cls->name);
996 /* classcache_find_loader ******************************************************
998 Find the class entry loaded by or constrained to a given loader
999 (internally used helper function)
1002 entry............the classcache_name_entry
1003 loader...........the loader to look for
1006 the classcache_class_entry for the given loader, or
1007 NULL if no entry was found
1009 *******************************************************************************/
1011 static classcache_class_entry * classcache_find_loader(
1012 classcache_name_entry * entry,
1013 classloader * loader)
1015 classcache_class_entry *clsen;
1016 classcache_loader_entry *lden;
1020 /* iterate over all class entries */
1021 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1023 /* check if this entry has already been loaded by initloader */
1024 for (lden = clsen->loaders; lden; lden = lden->next) {
1025 if (lden->loader == loader)
1026 return clsen; /* found */
1029 /* check if loader is constrained to this entry */
1030 for (lden = clsen->constraints; lden; lden = lden->next) {
1031 if (lden->loader == loader)
1032 return clsen; /* found */
1040 /* classcache_free_class_entry *************************************************
1042 Free the memory used by a class entry
1045 clsen............the classcache_class_entry to free
1047 *******************************************************************************/
1049 static void classcache_free_class_entry(classcache_class_entry * clsen)
1051 classcache_loader_entry *lden;
1052 classcache_loader_entry *next;
1056 for (lden = clsen->loaders; lden; lden = next) {
1058 FREE(lden, classcache_loader_entry);
1060 for (lden = clsen->constraints; lden; lden = next) {
1062 FREE(lden, classcache_loader_entry);
1065 FREE(clsen, classcache_class_entry);
1068 /* classcache_remove_class_entry ***********************************************
1070 Remove a classcache_class_entry from the list of possible resolution of
1072 (internally used helper function)
1075 entry............the classcache_name_entry
1076 clsen............the classcache_class_entry to remove
1078 *******************************************************************************/
1080 static void classcache_remove_class_entry(classcache_name_entry * entry,
1081 classcache_class_entry * clsen)
1083 classcache_class_entry **chain;
1088 chain = &(entry->classes);
1090 if (*chain == clsen) {
1091 *chain = clsen->next;
1092 classcache_free_class_entry(clsen);
1095 chain = &((*chain)->next);
1099 /* classcache_free_name_entry **************************************************
1101 Free the memory used by a name entry
1104 entry............the classcache_name_entry to free
1106 *******************************************************************************/
1108 static void classcache_free_name_entry(classcache_name_entry * entry)
1110 classcache_class_entry *clsen;
1111 classcache_class_entry *next;
1115 for (clsen = entry->classes; clsen; clsen = next) {
1117 classcache_free_class_entry(clsen);
1120 FREE(entry, classcache_name_entry);
1123 /* classcache_free *************************************************************
1125 Free the memory used by the class cache
1128 The class cache may not be used any more after this call, except
1129 when it is reinitialized with classcache_init.
1131 Note: NOT synchronized!
1133 *******************************************************************************/
1135 void classcache_free(void)
1138 classcache_name_entry *entry;
1139 classcache_name_entry *next;
1141 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1142 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1143 next = entry->hashlink;
1144 classcache_free_name_entry(entry);
1148 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1149 hashtable_classcache.size = 0;
1150 hashtable_classcache.entries = 0;
1151 hashtable_classcache.ptr = NULL;
1154 /* classcache_add_constraint ***************************************************
1156 Add a loading constraint
1159 a................first initiating loader
1160 b................second initiating loader
1161 classname........class name
1164 true.............everything ok, the constraint has been added,
1165 false............an exception has been thrown.
1167 Note: synchronized with global tablelock
1169 *******************************************************************************/
1171 #if defined(ENABLE_VERIFIER)
1172 bool classcache_add_constraint(classloader * a,
1176 classcache_name_entry *en;
1177 classcache_class_entry *clsenA;
1178 classcache_class_entry *clsenB;
1182 #ifdef CLASSCACHE_VERBOSE
1183 fprintf(stderr, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1184 utf_fprint_printable_ascii_classname(stderr, classname);
1185 fprintf(stderr, ")\n");
1188 /* a constraint with a == b is trivially satisfied */
1190 CLASSCACHE_COUNT(stat_trivial_constraints);
1196 en = classcache_new_name(classname);
1199 CLASSCACHE_COUNT(stat_nontriv_constraints);
1201 /* find the entry loaded by / constrained to each loader */
1202 clsenA = classcache_find_loader(en, a);
1203 clsenB = classcache_find_loader(en, b);
1205 if (clsenA && clsenB) {
1206 /* { both loaders have corresponding entries } */
1207 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1209 /* if the entries are the same, the constraint is already recorded */
1210 if (clsenA == clsenB)
1211 goto return_success;
1213 /* check if the entries can be merged */
1214 if (clsenA->classobj && clsenB->classobj
1215 && clsenA->classobj != clsenB->classobj) {
1216 /* no, the constraint is violated */
1217 *exceptionptr = exceptions_new_linkageerror(
1218 "loading constraint violated: ",clsenA->classobj);
1219 goto return_exception;
1222 /* yes, merge the entries */
1223 classcache_merge_class_entries(en,clsenA,clsenB);
1224 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1227 /* { at most one of the loaders has a corresponding entry } */
1229 /* set clsenA to the single class entry we have */
1234 /* { no loader has a corresponding entry } */
1235 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1237 /* create a new class entry with the constraint (a,b,en->name) */
1238 clsenA = NEW(classcache_class_entry);
1239 clsenA->classobj = NULL;
1240 clsenA->loaders = NULL;
1241 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1242 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1244 clsenA->next = en->classes;
1245 en->classes = clsenA;
1248 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1250 /* make b the loader that has no corresponding entry */
1254 /* loader b must be added to entry clsenA */
1255 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1260 CLASSCACHE_UNLOCK();
1264 CLASSCACHE_UNLOCK();
1265 return false; /* exception */
1267 #endif /* defined(ENABLE_VERIFIER) */
1269 /* classcache_add_constraints_for_params ***************************************
1271 Add loading constraints for the parameters and return type of
1275 a................first initiating loader
1276 b................second initiating loader
1277 m................methodinfo
1280 true.............everything ok, the constraints have been added,
1281 false............an exception has been thrown.
1283 Note: synchronized with global tablelock
1285 *******************************************************************************/
1287 #if defined(ENABLE_VERIFIER)
1288 bool classcache_add_constraints_for_params(classloader * a,
1296 /* a constraint with a == b is trivially satisfied */
1302 /* get the parsed descriptor */
1308 /* constrain the return type */
1310 if (md->returntype.type == TYPE_ADR) {
1311 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1312 return false; /* exception */
1315 /* constrain each reference type used in the parameters */
1317 td = md->paramtypes;
1320 if (td->type != TYPE_ADR)
1323 if (!classcache_add_constraint(a, b, td->classref->name))
1324 return false; /* exception */
1330 #endif /* defined(ENABLE_VERIFIER) */
1333 /* classcache_number_of_loaded_classes *****************************************
1335 Counts the number of loaded classes and returns it.
1337 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1340 *******************************************************************************/
1342 static s4 classcache_number_of_loaded_classes(void)
1344 classcache_name_entry *en;
1345 classcache_class_entry *clsen;
1349 /* initialize class counter */
1353 for (i = 0; i < hashtable_classcache.size; i++) {
1354 /* iterate over hashlink */
1356 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1357 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1359 if (en->name->text[0] == '$')
1362 /* iterate over classes with same name */
1364 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1365 /* get only loaded classes */
1367 if (clsen->classobj != NULL)
1377 /* classcache_get_loaded_class_count *******************************************
1379 Counts the number of loaded classes and returns it.
1381 *******************************************************************************/
1383 s4 classcache_get_loaded_class_count(void)
1389 count = classcache_number_of_loaded_classes();
1391 CLASSCACHE_UNLOCK();
1397 /* classcache_get_loaded_classes ***********************************************
1399 Returns an array of all loaded classes as array. The array is
1400 allocaed on the Java heap.
1402 *******************************************************************************/
1404 #if defined(ENABLE_JVMTI)
1405 void classcache_get_loaded_classes(s4 *class_count_ptr,
1406 classinfo ***classes_ptr)
1408 classinfo **classes;
1410 classcache_name_entry *en;
1411 classcache_class_entry *clsen;
1417 /* get the number of loaded classes and allocate the array */
1419 class_count = classcache_number_of_loaded_classes();
1421 classes = GCMNEW(classinfo*, class_count);
1423 /* look in every slot of the hashtable */
1425 for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1426 /* iterate over hashlink */
1428 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1429 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1431 if (en->name->text[0] == '$')
1434 /* iterate over classes with same name */
1436 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1437 /* get only loaded classes */
1439 if (clsen->classobj != NULL) {
1440 classes[j] = clsen->classobj;
1447 /* pass the return values */
1449 *class_count_ptr = class_count;
1450 *classes_ptr = classes;
1452 CLASSCACHE_UNLOCK();
1454 #endif /* defined(ENABLE_JVMTI) */
1457 /* classcache_foreach_loaded_class *********************************************
1459 Calls the given function for each loaded class.
1461 *******************************************************************************/
1463 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1466 classcache_name_entry *en;
1467 classcache_class_entry *clsen;
1472 /* look in every slot of the hashtable */
1474 for (i = 0; i < hashtable_classcache.size; i++) {
1475 /* iterate over hashlink */
1477 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1478 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1480 if (en->name->text[0] == '$')
1483 /* iterate over classes with same name */
1485 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1486 /* get only loaded classes */
1488 if (clsen->classobj != NULL) {
1489 (*func)(clsen->classobj, data);
1495 CLASSCACHE_UNLOCK();
1499 /*============================================================================*/
1501 /*============================================================================*/
1503 /* classcache_debug_dump *******************************************************
1505 Print the contents of the loaded class cache to a stream
1508 file.............output stream
1509 only.............if != NULL, only print entries for this name
1510 (Currently we print also the rest of the hash chain to
1511 get a feel for the average length of hash chains.)
1513 Note: synchronized with global tablelock
1515 *******************************************************************************/
1518 void classcache_debug_dump(FILE * file,utf *only)
1520 classcache_name_entry *c;
1521 classcache_class_entry *clsen;
1522 classcache_loader_entry *lden;
1527 fprintf(file, "\n=== [loaded class cache] =====================================\n\n");
1528 fprintf(file, "hash size : %d\n", (int) hashtable_classcache.size);
1529 fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries);
1530 fprintf(file, "\n");
1533 c = classcache_lookup_name(only);
1534 slot = 0; /* avoid compiler warning */
1538 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1539 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1542 for (; c; c = c->hashlink) {
1543 utf_fprint_printable_ascii_classname(file, c->name);
1544 fprintf(file, "\n");
1546 /* iterate over all class entries */
1547 for (clsen = c->classes; clsen; clsen = clsen->next) {
1548 if (clsen->classobj) {
1549 fprintf(file, " loaded %p\n", (void *) clsen->classobj);
1552 fprintf(file, " unresolved\n");
1554 fprintf(file, " loaders:");
1555 for (lden = clsen->loaders; lden; lden = lden->next) {
1556 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1558 fprintf(file, "\n constraints:");
1559 for (lden = clsen->constraints; lden; lden = lden->next) {
1560 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1562 fprintf(file, "\n");
1569 fprintf(file, "\n==============================================================\n\n");
1571 CLASSCACHE_UNLOCK();
1576 * These are local overrides for various environment variables in Emacs.
1577 * Please do not remove this and leave it at the end of the file, where
1578 * Emacs will automagically detect them.
1579 * ---------------------------------------------------------------------
1582 * indent-tabs-mode: t
1586 * vim:noexpandtab:sw=4:ts=4: