1 /* src/vmcore/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 $Id: classcache.c 7560 2007-03-23 18:51:41Z twisti $
36 #include "mm/memory.h"
38 #if defined(ENABLE_THREADS)
39 # include "threads/native/lock.h"
42 #include "toolbox/hashtable.h"
43 #include "toolbox/logging.h"
45 #include "vm/exceptions.h"
47 #include "vmcore/classcache.h"
48 #include "vmcore/utf8.h"
51 /*************************************************************************
55 The classcache has two functions:
57 1) caching the resolution of class references
58 2) storing and checking loading constraints
60 We will use the following terms in this description:
62 N a class name: a utf string
63 (N,L) a class reference with initiating loader L and class name N
64 C a class (object): the result of resolving a reference (N,L)
65 We will write resultion as
67 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
68 resolve to the same class C. So (N,L1,L2) means
71 The functions of the classcache require:
73 1) a mapping (N,L) |--> C for looking up prior resolution results.
74 2) storing the current set of loading constraints { (N,L1,L2) }
76 These functions can be rearranged like that:
78 a mapping N |--> (a mapping L |--> C or NULL,
79 a set of constraints {(L1,L2)})
81 Thus we can treat the mapping and constraints for each name N
82 separately. The implementation does this by keeping a hash table
83 mapping a name N to a `classcache_name_entry` which contains all
84 info with respect to N.
86 For a class name N we can define an equivalence relation ~N~ on
89 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
91 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
93 Also, if two references (N,L1) and (N,L2) resolve to the same class C
94 we have L1 ~N~ L2 because class loaders are required to return
95 consistent resolutions for a name N [XXX].
97 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
99 Cx...is a class C or NULL
100 IL...is the set of initiating loaders
101 CL...is the set of constrained loaders
103 Such a tuple is called `classcache_class_entry` in the source code.
105 The following holds for each tuple (Cx,IL,CL):
107 . (Cx is NULL) implies IL = {}.
109 . If Cx is a class, IL is the set of loaders that have been
110 recorded as initiating loaders for Cx. IL may be the
111 empty set {} in case Cx has already been defined but no
112 initiating loader has been recorded, yet.
114 . (IL u CL) is a subset of an equivalence class of ~N~.
116 (This means that all loaders in IL and CL must resolve
117 the name N to the same class.)
119 The following holds for the set of tuples { (Cx,IL,CL) }:
121 . For a given class C there is at most one tuple with Cx = C
122 in the set. (There may be an arbitrary number of tuples
123 with Cx = NULL, however.)
125 . For a given loader L there is at most one tuple with
128 The implementation stores sets of loaders as linked lists of
129 `classcache_loader_entry`s.
131 Comments about manipulating the classcache can be found in the
132 individual functions below.
134 *************************************************************************/
137 /* initial number of slots in the classcache hash table */
138 #define CLASSCACHE_INIT_SIZE 2048
140 /*============================================================================*/
142 /*============================================================================*/
144 /* #define CLASSCACHE_VERBOSE */
146 /*============================================================================*/
148 /*============================================================================*/
150 /*#define CLASSCACHE_STATS*/
152 #ifdef CLASSCACHE_STATS
153 static int stat_classnames_stored = 0;
154 static int stat_classes_stored = 0;
155 static int stat_trivial_constraints = 0;
156 static int stat_nontriv_constraints = 0;
157 static int stat_nontriv_constraints_both = 0;
158 static int stat_nontriv_constraints_merged = 0;
159 static int stat_nontriv_constraints_one = 0;
160 static int stat_nontriv_constraints_none = 0;
161 static int stat_new_loader_entry = 0;
162 static int stat_merge_class_entries = 0;
163 static int stat_merge_loader_entries = 0;
164 static int stat_lookup = 0;
165 static int stat_lookup_class_entry_checked = 0;
166 static int stat_lookup_loader_checked = 0;
167 static int stat_lookup_name = 0;
168 static int stat_lookup_name_entry = 0;
169 static int stat_lookup_name_notfound = 0;
170 static int stat_lookup_new_name = 0;
171 static int stat_lookup_new_name_entry = 0;
172 static int stat_lookup_new_name_collisions = 0;
173 static int stat_rehash_names = 0;
174 static int stat_rehash_names_collisions = 0;
176 #define CLASSCACHE_COUNT(cnt) (cnt)++
177 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
179 void classcache_print_statistics(FILE *file) {
180 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
181 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
182 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
183 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
184 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
185 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
186 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
187 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
188 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
189 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
190 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
191 fprintf(file,"lookups : %8d\n",stat_lookup);
192 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
193 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
194 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
195 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
196 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
197 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
198 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
199 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
200 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
201 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
204 #define CLASSCACHE_COUNT(cnt)
205 #define CLASSCACHE_COUNTIF(cond,cnt)
208 /*============================================================================*/
209 /* THREAD-SAFE LOCKING */
210 /*============================================================================*/
212 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
213 /* CAUTION: The static functions below are */
214 /* NOT synchronized! */
215 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
217 #if defined(ENABLE_THREADS)
218 # define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
219 # define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
221 # define CLASSCACHE_LOCK()
222 # define CLASSCACHE_UNLOCK()
225 /*============================================================================*/
226 /* GLOBAL VARIABLES */
227 /*============================================================================*/
229 hashtable hashtable_classcache;
231 #if defined(ENABLE_THREADS)
232 static java_objectheader *lock_hashtable_classcache;
236 /*============================================================================*/
238 /*============================================================================*/
242 static void classcache_free_class_entry(classcache_class_entry *clsen);
243 static void classcache_remove_class_entry(classcache_name_entry *en,
244 classcache_class_entry *clsen);
246 /* hash function to use */
248 #define CLASSCACHE_HASH utf_full_hashkey
250 /* classcache_init *************************************************************
252 Initialize the class cache
254 Note: NOT synchronized!
256 *******************************************************************************/
258 bool classcache_init(void)
260 /* create the hashtable */
262 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
264 #if defined(ENABLE_THREADS)
265 /* create utf hashtable lock object */
267 lock_hashtable_classcache = NEW(java_objectheader);
269 lock_init_object_lock(lock_hashtable_classcache);
272 /* everything's ok */
277 /* classcache_new_loader_entry *************************************************
279 Create a new classcache_loader_entry struct
280 (internally used helper function)
283 loader...........the ClassLoader object
284 next.............the next classcache_loader_entry
287 the new classcache_loader_entry
289 *******************************************************************************/
291 static classcache_loader_entry * classcache_new_loader_entry(
292 classloader * loader,
293 classcache_loader_entry * next)
295 classcache_loader_entry *lden;
297 lden = NEW(classcache_loader_entry);
298 lden->loader = loader;
300 CLASSCACHE_COUNT(stat_new_loader_entry);
305 /* classcache_merge_loaders ****************************************************
307 Merge two lists of loaders into one
308 (internally used helper function)
311 lista............first list (may be NULL)
312 listb............second list (may be NULL)
315 the merged list (may be NULL)
318 The lists given as arguments are destroyed!
320 *******************************************************************************/
322 static classcache_loader_entry * classcache_merge_loaders(
323 classcache_loader_entry * lista,
324 classcache_loader_entry * listb)
326 classcache_loader_entry *result;
327 classcache_loader_entry *ldenA;
328 classcache_loader_entry *ldenB;
329 classcache_loader_entry **chain;
331 CLASSCACHE_COUNT(stat_merge_loader_entries);
333 /* XXX This is a quadratic algorithm. If this ever
334 * becomes a problem, the loader lists should be
335 * stored as sorted lists and merged in linear time. */
340 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
342 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
343 if (ldenB->loader == ldenA->loader)
347 /* this loader is only in lista */
349 chain = &(ldenA->next);
352 /* XXX free the duplicated element */
356 /* concat listb to the result */
362 /* classcache_merge_class_entries **********************************************
364 Merge two `classcache_class_entry`s into one.
365 (internally used helper function)
368 en...............the classcache_name_entry containing both class entries
369 clsenA...........first class entry, will receive the result
370 clsenB...........second class entry
373 Either both entries must have the same classobj, or one of them has
377 clsenB is freed by this function!
379 *******************************************************************************/
381 static void classcache_merge_class_entries(classcache_name_entry *en,
382 classcache_class_entry *clsenA,
383 classcache_class_entry *clsenB)
385 #ifdef CLASSCACHE_VERBOSE
386 char logbuffer[1024];
392 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
394 #ifdef CLASSCACHE_VERBOSE
395 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
396 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
397 if (clsenA->classobj)
398 utf_cat_classname(logbuffer, clsenA->classobj->name);
399 if (clsenB->classobj)
400 utf_cat_classname(logbuffer, clsenB->classobj->name);
401 log_println(logbuffer);
404 CLASSCACHE_COUNT(stat_merge_class_entries);
406 /* clsenB will be merged into clsenA */
407 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
408 clsenB->loaders = NULL; /* these have been freed or reused */
410 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
411 clsenB->constraints);
412 clsenB->constraints = NULL; /* these have been freed or reused */
414 if (!clsenA->classobj)
415 clsenA->classobj = clsenB->classobj;
417 /* remove clsenB from the list of class entries */
418 classcache_remove_class_entry(en, clsenB);
422 /* classcache_lookup_name ******************************************************
424 Lookup a name in the first level of the cache
425 (internally used helper function)
428 name.............the name to look up
431 a pointer to the classcache_name_entry for this name, or
432 null if no entry was found.
434 *******************************************************************************/
436 static classcache_name_entry *classcache_lookup_name(utf *name)
438 classcache_name_entry *c; /* hash table element */
439 u4 key; /* hashkey computed from classname */
440 u4 slot; /* slot in hashtable */
442 CLASSCACHE_COUNT(stat_lookup_name);
444 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
445 slot = key & (hashtable_classcache.size - 1);
446 c = hashtable_classcache.ptr[slot];
448 /* search external hash chain for the entry */
451 /* entry found in hashtable */
452 CLASSCACHE_COUNT(stat_lookup_name_entry);
457 c = c->hashlink; /* next element in external chain */
462 CLASSCACHE_COUNT(stat_lookup_name_notfound);
467 /* classcache_new_name *********************************************************
469 Return a classcache_name_entry for the given name. The entry is created
470 if it is not already in the cache.
471 (internally used helper function)
474 name.............the name to look up / create an entry for
477 a pointer to the classcache_name_entry for this name
479 *******************************************************************************/
481 static classcache_name_entry *classcache_new_name(utf *name)
483 classcache_name_entry *c; /* hash table element */
484 u4 key; /* hashkey computed from classname */
485 u4 slot; /* slot in hashtable */
488 CLASSCACHE_COUNT(stat_lookup_new_name);
490 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
491 slot = key & (hashtable_classcache.size - 1);
492 c = hashtable_classcache.ptr[slot];
494 /* search external hash chain for the entry */
497 /* entry found in hashtable */
498 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
503 c = c->hashlink; /* next element in external chain */
506 /* location in hashtable found, create new entry */
508 c = NEW(classcache_name_entry);
513 /* insert entry into hashtable */
514 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
515 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
516 hashtable_classcache.ptr[slot] = c;
518 /* update number of hashtable-entries */
519 hashtable_classcache.entries++;
520 CLASSCACHE_COUNT(stat_classnames_stored);
522 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
523 /* reorganization of hashtable */
525 classcache_name_entry *c2;
526 hashtable newhash; /* the new hashtable */
528 CLASSCACHE_COUNT(stat_rehash_names);
530 /* create new hashtable, double the size */
532 hashtable_create(&newhash, hashtable_classcache.size * 2);
533 newhash.entries = hashtable_classcache.entries;
535 /* transfer elements to new hashtable */
537 for (i = 0; i < hashtable_classcache.size; i++) {
538 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
540 classcache_name_entry *nextc = c2->hashlink;
542 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
544 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
545 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
546 newhash.ptr[newslot] = c2;
552 /* dispose old table */
554 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
555 hashtable_classcache = newhash;
562 /* classcache_lookup ***********************************************************
564 Lookup a possibly loaded class
567 initloader.......initiating loader for resolving the class name
568 classname........class name to look up
571 The return value is a pointer to the cached class object,
572 or NULL, if the class is not in the cache.
574 Note: synchronized with global tablelock
576 *******************************************************************************/
578 classinfo *classcache_lookup(classloader *initloader, utf *classname)
580 classcache_name_entry *en;
581 classcache_class_entry *clsen;
582 classcache_loader_entry *lden;
583 classinfo *cls = NULL;
587 CLASSCACHE_COUNT(stat_lookup);
588 en = classcache_lookup_name(classname);
591 /* iterate over all class entries */
593 for (clsen = en->classes; clsen; clsen = clsen->next) {
594 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
595 /* check if this entry has been loaded by initloader */
597 for (lden = clsen->loaders; lden; lden = lden->next) {
598 CLASSCACHE_COUNT(stat_lookup_loader_checked);
599 if (lden->loader == initloader) {
600 /* found the loaded class entry */
602 assert(clsen->classobj);
603 cls = clsen->classobj;
616 /* classcache_lookup_defined ***************************************************
618 Lookup a class with the given name and defining loader
621 defloader........defining loader
622 classname........class name
625 The return value is a pointer to the cached class object,
626 or NULL, if the class is not in the cache.
628 *******************************************************************************/
630 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
632 classcache_name_entry *en;
633 classcache_class_entry *clsen;
634 classinfo *cls = NULL;
638 en = classcache_lookup_name(classname);
641 /* iterate over all class entries */
642 for (clsen = en->classes; clsen; clsen = clsen->next) {
643 if (!clsen->classobj)
646 /* check if this entry has been defined by defloader */
647 if (clsen->classobj->classloader == defloader) {
648 cls = clsen->classobj;
660 /* classcache_lookup_defined_or_initiated **************************************
662 Lookup a class that has been defined or initiated by the given loader
665 loader...........defining or initiating loader
666 classname........class name to look up
669 The return value is a pointer to the cached class object,
670 or NULL, if the class is not in the cache.
672 Note: synchronized with global tablelock
674 *******************************************************************************/
676 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
679 classcache_name_entry *en;
680 classcache_class_entry *clsen;
681 classcache_loader_entry *lden;
682 classinfo *cls = NULL;
686 en = classcache_lookup_name(classname);
689 /* iterate over all class entries */
691 for (clsen = en->classes; clsen; clsen = clsen->next) {
693 /* check if this entry has been defined by loader */
694 if (clsen->classobj && clsen->classobj->classloader == loader) {
695 cls = clsen->classobj;
699 /* check if this entry has been initiated by loader */
700 for (lden = clsen->loaders; lden; lden = lden->next) {
701 if (lden->loader == loader) {
702 /* found the loaded class entry */
704 assert(clsen->classobj);
705 cls = clsen->classobj;
718 /* classcache_store ************************************************************
720 Store a loaded class. If a class of the same name has already been stored
721 with the same initiating loader, then the given class CLS is freed (if
722 possible) and the previously stored class is returned.
725 initloader.......initiating loader used to load the class
726 (may be NULL indicating the bootstrap loader)
727 cls..............class object to cache
728 mayfree..........true if CLS may be freed in case another class is
732 cls..............everything ok, the class was stored in the cache,
733 other classinfo..another class with the same (initloader,name) has been
734 stored earlier. CLS has been freed[1] and the earlier
735 stored class is returned.
736 NULL.............an exception has been thrown.
738 Note: synchronized with global tablelock
740 [1]...in case MAYFREE is true
742 *******************************************************************************/
744 classinfo *classcache_store(classloader *initloader, classinfo *cls,
747 classcache_name_entry *en;
748 classcache_class_entry *clsen;
749 classcache_class_entry *clsenB;
750 classcache_loader_entry *lden;
751 #ifdef CLASSCACHE_VERBOSE
752 char logbuffer[1024];
756 assert(cls->state & CLASS_LOADED);
760 #ifdef CLASSCACHE_VERBOSE
761 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
762 utf_cat_classname(logbuffer, cls->name);
763 strcat(logbuffer,")");
764 log_println(logbuffer);
767 en = classcache_new_name(cls->name);
771 /* iterate over all class entries */
772 for (clsen = en->classes; clsen; clsen = clsen->next) {
774 /* check if this entry has already been loaded by initloader */
775 for (lden = clsen->loaders; lden; lden = lden->next) {
776 if (lden->loader == initloader) {
777 if (clsen->classobj != cls) {
778 /* A class with the same (initloader,name) pair has been stored already. */
779 /* We free the given class and return the earlier one. */
780 #ifdef CLASSCACHE_VERBOSE
781 log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
783 assert(clsen->classobj);
786 cls = clsen->classobj;
792 /* {This entry has not been resolved with initloader} */
794 /* check if initloader is constrained to this entry */
795 for (lden = clsen->constraints; lden; lden = lden->next) {
796 if (lden->loader == initloader) {
797 /* we have to use this entry. check if it has been resolved */
798 if (clsen->classobj) {
799 /* check if is has already been resolved to another class */
800 if (clsen->classobj != cls) {
801 /* a loading constraint is violated */
802 exceptions_throw_linkageerror("loading constraint violated: ", cls);
803 goto return_exception;
806 /* record initloader as initiating loader */
807 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
811 /* {this is the first resolution for this entry} */
812 /* record initloader as initiating loader */
813 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
815 /* maybe we can merge this entry with another one */
816 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
817 /* we dont want the entry that we have already */
818 if (clsenB->classobj == cls) {
819 /* this entry has the same classobj. let's merge them */
820 classcache_merge_class_entries(en,clsen,clsenB);
825 /* record the loaded class object */
826 clsen->classobj = cls;
827 CLASSCACHE_COUNT(stat_classes_stored);
836 /* {There is no class entry containing initloader as initiating
837 * or constrained loader.} */
839 /* we look for a class entry with the same classobj we want to store */
840 for (clsen = en->classes; clsen; clsen = clsen->next) {
841 if (clsen->classobj == cls) {
842 /* this entry is about the same classobj. let's use it */
843 /* check if this entry has already been loaded by initloader */
844 for (lden = clsen->loaders; lden; lden = lden->next) {
845 if (lden->loader == initloader)
848 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
853 /* create a new class entry for this class object with */
854 /* initiating loader initloader */
856 clsen = NEW(classcache_class_entry);
857 clsen->classobj = cls;
858 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
859 clsen->constraints = NULL;
861 clsen->next = en->classes;
863 CLASSCACHE_COUNT(stat_classes_stored);
866 #ifdef CLASSCACHE_VERBOSE
867 classcache_debug_dump(stdout,cls->name);
874 return NULL; /* exception */
877 /* classcache_store_unique *****************************************************
879 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
880 aroung classcache_store that throws an exception if a class with the same
881 name has already been loaded by the bootstrap loader.
883 This function is used to register a few special classes during startup.
884 It should not be used otherwise.
887 cls..............class object to cache
890 true.............everything ok, the class was stored.
891 false............an exception has been thrown.
893 Note: synchronized with global tablelock
895 *******************************************************************************/
897 bool classcache_store_unique(classinfo *cls)
901 result = classcache_store(NULL,cls,false);
906 exceptions_throw_internalerror("class already stored in the class cache");
913 /* classcache_store_defined ****************************************************
915 Store a loaded class after it has been defined. If the class has already
916 been defined by the same defining loader in another thread, free the given
917 class and returned the one which has been defined earlier.
920 cls..............class object to store. classloader must be set
921 (classloader may be NULL, for bootloader)
924 cls..............everything ok, the class was stored the cache,
925 other classinfo..the class had already been defined, CLS was freed, the
926 class which was defined earlier is returned,
927 NULL.............an exception has been thrown.
929 *******************************************************************************/
931 classinfo *classcache_store_defined(classinfo *cls)
933 classcache_name_entry *en;
934 classcache_class_entry *clsen;
935 #ifdef CLASSCACHE_VERBOSE
936 char logbuffer[1024];
940 assert(cls->state & CLASS_LOADED);
944 #ifdef CLASSCACHE_VERBOSE
945 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
946 utf_cat_classname(logbuffer, cls->name);
947 strcat(logbuffer,")");
948 log_println(logbuffer);
951 en = classcache_new_name(cls->name);
955 /* iterate over all class entries */
956 for (clsen = en->classes; clsen; clsen = clsen->next) {
958 /* check if this class has been defined by the same classloader */
959 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
960 /* we found an earlier definition, delete the newer one */
961 /* (if it is a different classinfo) */
962 if (clsen->classobj != cls) {
963 #ifdef CLASSCACHE_VERBOSE
964 log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
967 cls = clsen->classobj;
973 /* create a new class entry for this class object */
974 /* the list of initiating loaders is empty at this point */
976 clsen = NEW(classcache_class_entry);
977 clsen->classobj = cls;
978 clsen->loaders = NULL;
979 clsen->constraints = NULL;
981 clsen->next = en->classes;
983 CLASSCACHE_COUNT(stat_classes_stored);
986 #ifdef CLASSCACHE_VERBOSE
987 classcache_debug_dump(stdout,cls->name);
993 /* classcache_find_loader ******************************************************
995 Find the class entry loaded by or constrained to a given loader
996 (internally used helper function)
999 entry............the classcache_name_entry
1000 loader...........the loader to look for
1003 the classcache_class_entry for the given loader, or
1004 NULL if no entry was found
1006 *******************************************************************************/
1008 static classcache_class_entry * classcache_find_loader(
1009 classcache_name_entry * entry,
1010 classloader * loader)
1012 classcache_class_entry *clsen;
1013 classcache_loader_entry *lden;
1017 /* iterate over all class entries */
1018 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1020 /* check if this entry has already been loaded by initloader */
1021 for (lden = clsen->loaders; lden; lden = lden->next) {
1022 if (lden->loader == loader)
1023 return clsen; /* found */
1026 /* check if loader is constrained to this entry */
1027 for (lden = clsen->constraints; lden; lden = lden->next) {
1028 if (lden->loader == loader)
1029 return clsen; /* found */
1037 /* classcache_free_class_entry *************************************************
1039 Free the memory used by a class entry
1042 clsen............the classcache_class_entry to free
1044 *******************************************************************************/
1046 static void classcache_free_class_entry(classcache_class_entry * clsen)
1048 classcache_loader_entry *lden;
1049 classcache_loader_entry *next;
1053 for (lden = clsen->loaders; lden; lden = next) {
1055 FREE(lden, classcache_loader_entry);
1057 for (lden = clsen->constraints; lden; lden = next) {
1059 FREE(lden, classcache_loader_entry);
1062 FREE(clsen, classcache_class_entry);
1065 /* classcache_remove_class_entry ***********************************************
1067 Remove a classcache_class_entry from the list of possible resolution of
1069 (internally used helper function)
1072 entry............the classcache_name_entry
1073 clsen............the classcache_class_entry to remove
1075 *******************************************************************************/
1077 static void classcache_remove_class_entry(classcache_name_entry * entry,
1078 classcache_class_entry * clsen)
1080 classcache_class_entry **chain;
1085 chain = &(entry->classes);
1087 if (*chain == clsen) {
1088 *chain = clsen->next;
1089 classcache_free_class_entry(clsen);
1092 chain = &((*chain)->next);
1096 /* classcache_free_name_entry **************************************************
1098 Free the memory used by a name entry
1101 entry............the classcache_name_entry to free
1103 *******************************************************************************/
1105 static void classcache_free_name_entry(classcache_name_entry * entry)
1107 classcache_class_entry *clsen;
1108 classcache_class_entry *next;
1112 for (clsen = entry->classes; clsen; clsen = next) {
1114 classcache_free_class_entry(clsen);
1117 FREE(entry, classcache_name_entry);
1120 /* classcache_free *************************************************************
1122 Free the memory used by the class cache
1125 The class cache may not be used any more after this call, except
1126 when it is reinitialized with classcache_init.
1128 Note: NOT synchronized!
1130 *******************************************************************************/
1132 void classcache_free(void)
1135 classcache_name_entry *entry;
1136 classcache_name_entry *next;
1138 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1139 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1140 next = entry->hashlink;
1141 classcache_free_name_entry(entry);
1145 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1146 hashtable_classcache.size = 0;
1147 hashtable_classcache.entries = 0;
1148 hashtable_classcache.ptr = NULL;
1151 /* classcache_add_constraint ***************************************************
1153 Add a loading constraint
1156 a................first initiating loader
1157 b................second initiating loader
1158 classname........class name
1161 true.............everything ok, the constraint has been added,
1162 false............an exception has been thrown.
1164 Note: synchronized with global tablelock
1166 *******************************************************************************/
1168 #if defined(ENABLE_VERIFIER)
1169 bool classcache_add_constraint(classloader * a,
1173 classcache_name_entry *en;
1174 classcache_class_entry *clsenA;
1175 classcache_class_entry *clsenB;
1179 #ifdef CLASSCACHE_VERBOSE
1181 log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1182 utf_fprint_printable_ascii_classname(stdout, classname);
1187 /* a constraint with a == b is trivially satisfied */
1189 CLASSCACHE_COUNT(stat_trivial_constraints);
1195 en = classcache_new_name(classname);
1198 CLASSCACHE_COUNT(stat_nontriv_constraints);
1200 /* find the entry loaded by / constrained to each loader */
1201 clsenA = classcache_find_loader(en, a);
1202 clsenB = classcache_find_loader(en, b);
1204 if (clsenA && clsenB) {
1205 /* { both loaders have corresponding entries } */
1206 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1208 /* if the entries are the same, the constraint is already recorded */
1209 if (clsenA == clsenB)
1210 goto return_success;
1212 /* check if the entries can be merged */
1213 if (clsenA->classobj && clsenB->classobj
1214 && clsenA->classobj != clsenB->classobj) {
1215 /* no, the constraint is violated */
1216 exceptions_throw_linkageerror("loading constraint violated: ",
1218 goto return_exception;
1221 /* yes, merge the entries */
1222 classcache_merge_class_entries(en,clsenA,clsenB);
1223 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1226 /* { at most one of the loaders has a corresponding entry } */
1228 /* set clsenA to the single class entry we have */
1233 /* { no loader has a corresponding entry } */
1234 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1236 /* create a new class entry with the constraint (a,b,en->name) */
1237 clsenA = NEW(classcache_class_entry);
1238 clsenA->classobj = NULL;
1239 clsenA->loaders = NULL;
1240 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1241 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1243 clsenA->next = en->classes;
1244 en->classes = clsenA;
1247 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1249 /* make b the loader that has no corresponding entry */
1253 /* loader b must be added to entry clsenA */
1254 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1259 CLASSCACHE_UNLOCK();
1263 CLASSCACHE_UNLOCK();
1264 return false; /* exception */
1266 #endif /* defined(ENABLE_VERIFIER) */
1268 /* classcache_add_constraints_for_params ***************************************
1270 Add loading constraints for the parameters and return type of
1274 a................first initiating loader
1275 b................second initiating loader
1276 m................methodinfo
1279 true.............everything ok, the constraints have been added,
1280 false............an exception has been thrown.
1282 Note: synchronized with global tablelock
1284 *******************************************************************************/
1286 #if defined(ENABLE_VERIFIER)
1287 bool classcache_add_constraints_for_params(classloader * a,
1295 /* a constraint with a == b is trivially satisfied */
1301 /* get the parsed descriptor */
1307 /* constrain the return type */
1309 if (md->returntype.type == TYPE_ADR) {
1310 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1311 return false; /* exception */
1314 /* constrain each reference type used in the parameters */
1316 td = md->paramtypes;
1319 if (td->type != TYPE_ADR)
1322 if (!classcache_add_constraint(a, b, td->classref->name))
1323 return false; /* exception */
1329 #endif /* defined(ENABLE_VERIFIER) */
1332 /* classcache_number_of_loaded_classes *****************************************
1334 Counts the number of loaded classes and returns it.
1336 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1339 *******************************************************************************/
1341 static s4 classcache_number_of_loaded_classes(void)
1343 classcache_name_entry *en;
1344 classcache_class_entry *clsen;
1348 /* initialize class counter */
1352 for (i = 0; i < hashtable_classcache.size; i++) {
1353 /* iterate over hashlink */
1355 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1356 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1358 if (en->name->text[0] == '$')
1361 /* iterate over classes with same name */
1363 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1364 /* get only loaded classes */
1366 if (clsen->classobj != NULL)
1376 /* classcache_get_loaded_class_count *******************************************
1378 Counts the number of loaded classes and returns it.
1380 *******************************************************************************/
1382 s4 classcache_get_loaded_class_count(void)
1388 count = classcache_number_of_loaded_classes();
1390 CLASSCACHE_UNLOCK();
1396 /* classcache_get_loaded_classes ***********************************************
1398 Returns an array of all loaded classes as array. The array is
1399 allocaed on the Java heap.
1401 *******************************************************************************/
1403 #if defined(ENABLE_JVMTI)
1404 void classcache_get_loaded_classes(s4 *class_count_ptr,
1405 classinfo ***classes_ptr)
1407 classinfo **classes;
1409 classcache_name_entry *en;
1410 classcache_class_entry *clsen;
1416 /* get the number of loaded classes and allocate the array */
1418 class_count = classcache_number_of_loaded_classes();
1420 classes = GCMNEW(classinfo*, class_count);
1422 /* look in every slot of the hashtable */
1424 for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1425 /* iterate over hashlink */
1427 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1428 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1430 if (en->name->text[0] == '$')
1433 /* iterate over classes with same name */
1435 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1436 /* get only loaded classes */
1438 if (clsen->classobj != NULL) {
1439 classes[j] = clsen->classobj;
1446 /* pass the return values */
1448 *class_count_ptr = class_count;
1449 *classes_ptr = classes;
1451 CLASSCACHE_UNLOCK();
1453 #endif /* defined(ENABLE_JVMTI) */
1456 /* classcache_foreach_loaded_class *********************************************
1458 Calls the given function for each loaded class.
1460 *******************************************************************************/
1462 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1465 classcache_name_entry *en;
1466 classcache_class_entry *clsen;
1471 /* look in every slot of the hashtable */
1473 for (i = 0; i < hashtable_classcache.size; i++) {
1474 /* iterate over hashlink */
1476 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1477 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1479 if (en->name->text[0] == '$')
1482 /* iterate over classes with same name */
1484 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1485 /* get only loaded classes */
1487 if (clsen->classobj != NULL) {
1488 (*func)(clsen->classobj, data);
1494 CLASSCACHE_UNLOCK();
1498 /*============================================================================*/
1500 /*============================================================================*/
1502 /* classcache_debug_dump *******************************************************
1504 Print the contents of the loaded class cache to a stream
1507 file.............output stream
1508 only.............if != NULL, only print entries for this name
1509 (Currently we print also the rest of the hash chain to
1510 get a feel for the average length of hash chains.)
1512 Note: synchronized with global tablelock
1514 *******************************************************************************/
1517 void classcache_debug_dump(FILE * file,utf *only)
1519 classcache_name_entry *c;
1520 classcache_class_entry *clsen;
1521 classcache_loader_entry *lden;
1526 log_println("=== [loaded class cache] =====================================");
1527 log_println("hash size : %d", (int) hashtable_classcache.size);
1528 log_println("hash entries: %d", (int) hashtable_classcache.entries);
1532 c = classcache_lookup_name(only);
1533 slot = 0; /* avoid compiler warning */
1537 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1538 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1541 for (; c; c = c->hashlink) {
1542 utf_fprint_printable_ascii_classname(file, c->name);
1543 fprintf(file, "\n");
1545 /* iterate over all class entries */
1546 for (clsen = c->classes; clsen; clsen = clsen->next) {
1547 if (clsen->classobj) {
1548 log_println(" loaded %p", (void *) clsen->classobj);
1551 log_println(" unresolved");
1555 log_print(" loaders: ");
1556 for (lden = clsen->loaders; lden; lden = lden->next) {
1557 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1562 log_print(" constraints: ");
1563 for (lden = clsen->constraints; lden; lden = lden->next) {
1564 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1573 fprintf(file, "\n==============================================================\n\n");
1575 CLASSCACHE_UNLOCK();
1580 * These are local overrides for various environment variables in Emacs.
1581 * Please do not remove this and leave it at the end of the file, where
1582 * Emacs will automagically detect them.
1583 * ---------------------------------------------------------------------
1586 * indent-tabs-mode: t
1590 * vim:noexpandtab:sw=4:ts=4: