1 /* src/vm/classcache.c - loaded class cache and loading constraints
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
29 Changes: Christian Thalinger
31 $Id: classcache.c 5192 2006-07-31 14:21:15Z twisti $
41 #include "mm/memory.h"
43 #if defined(ENABLE_THREADS)
44 # include "threads/native/lock.h"
47 #include "vm/classcache.h"
48 #include "vm/exceptions.h"
49 #include "vm/hashtable.h"
50 #include "vm/stringlocal.h"
54 /*************************************************************************
58 The classcache has two functions:
60 1) caching the resolution of class references
61 2) storing and checking loading constraints
63 We will use the following terms in this description:
65 N a class name: a utf string
66 (N,L) a class reference with initiating loader L and class name N
67 C a class (object): the result of resolving a reference (N,L)
68 We will write resultion as
70 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
71 resolve to the same class C. So (N,L1,L2) means
74 The functions of the classcache require:
76 1) a mapping (N,L) |--> C for looking up prior resolution results.
77 2) storing the current set of loading constraints { (N,L1,L2) }
79 These functions can be rearranged like that:
81 a mapping N |--> (a mapping L |--> C or NULL,
82 a set of constraints {(L1,L2)})
84 Thus we can treat the mapping and constraints for each name N
85 separately. The implementation does this by keeping a hash table
86 mapping a name N to a `classcache_name_entry` which contains all
87 info with respect to N.
89 For a class name N we can define an equivalence relation ~N~ on
92 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
94 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
96 Also, if two references (N,L1) and (N,L2) resolve to the same class C
97 we have L1 ~N~ L2 because class loaders are required to return
98 consistent resolutions for a name N [XXX].
100 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
102 Cx...is a class C or NULL
103 IL...is the set of initiating loaders
104 CL...is the set of constrained loaders
106 Such a tuple is called `classcache_class_entry` in the source code.
108 The following holds for each tuple (Cx,IL,CL):
110 . (Cx is NULL) implies IL = {}.
112 . If Cx is a class, IL is the set of loaders that have been
113 recorded as initiating loaders for Cx. IL may be the
114 empty set {} in case Cx has already been defined but no
115 initiating loader has been recorded, yet.
117 . (IL u CL) is a subset of an equivalence class of ~N~.
119 (This means that all loaders in IL and CL must resolve
120 the name N to the same class.)
122 The following holds for the set of tuples { (Cx,IL,CL) }:
124 . For a given class C there is at most one tuple with Cx = C
125 in the set. (There may be an arbitrary number of tuples
126 with Cx = NULL, however.)
128 . For a given loader L there is at most one tuple with
131 The implementation stores sets of loaders as linked lists of
132 `classcache_loader_entry`s.
134 Comments about manipulating the classcache can be found in the
135 individual functions below.
137 *************************************************************************/
140 /* initial number of slots in the classcache hash table */
141 #define CLASSCACHE_INIT_SIZE 2048
143 /*============================================================================*/
145 /*============================================================================*/
147 /*#define CLASSCACHE_VERBOSE*/
149 /*============================================================================*/
151 /*============================================================================*/
153 /*#define CLASSCACHE_STATS*/
155 #ifdef CLASSCACHE_STATS
156 static int stat_classnames_stored = 0;
157 static int stat_classes_stored = 0;
158 static int stat_trivial_constraints = 0;
159 static int stat_nontriv_constraints = 0;
160 static int stat_nontriv_constraints_both = 0;
161 static int stat_nontriv_constraints_merged = 0;
162 static int stat_nontriv_constraints_one = 0;
163 static int stat_nontriv_constraints_none = 0;
164 static int stat_new_loader_entry = 0;
165 static int stat_merge_class_entries = 0;
166 static int stat_merge_loader_entries = 0;
167 static int stat_lookup = 0;
168 static int stat_lookup_class_entry_checked = 0;
169 static int stat_lookup_loader_checked = 0;
170 static int stat_lookup_name = 0;
171 static int stat_lookup_name_entry = 0;
172 static int stat_lookup_name_notfound = 0;
173 static int stat_lookup_new_name = 0;
174 static int stat_lookup_new_name_entry = 0;
175 static int stat_lookup_new_name_collisions = 0;
176 static int stat_rehash_names = 0;
177 static int stat_rehash_names_collisions = 0;
179 #define CLASSCACHE_COUNT(cnt) (cnt)++
180 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
182 void classcache_print_statistics(FILE *file) {
183 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
184 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
185 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
186 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
187 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
188 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
189 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
190 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
191 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
192 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
193 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
194 fprintf(file,"lookups : %8d\n",stat_lookup);
195 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
196 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
197 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
198 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
199 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
200 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
201 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
202 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
203 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
204 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
207 #define CLASSCACHE_COUNT(cnt)
208 #define CLASSCACHE_COUNTIF(cond,cnt)
211 /*============================================================================*/
212 /* THREAD-SAFE LOCKING */
213 /*============================================================================*/
215 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
216 /* CAUTION: The static functions below are */
217 /* NOT synchronized! */
218 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
220 #if defined(ENABLE_THREADS)
221 # define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
222 # define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
224 # define CLASSCACHE_LOCK()
225 # define CLASSCACHE_UNLOCK()
228 /*============================================================================*/
229 /* GLOBAL VARIABLES */
230 /*============================================================================*/
232 hashtable hashtable_classcache;
234 #if defined(ENABLE_THREADS)
235 static java_objectheader *lock_hashtable_classcache;
239 /*============================================================================*/
241 /*============================================================================*/
245 static void classcache_free_class_entry(classcache_class_entry *clsen);
246 static void classcache_remove_class_entry(classcache_name_entry *en,
247 classcache_class_entry *clsen);
249 /* hash function to use */
251 #define CLASSCACHE_HASH utf_full_hashkey
253 /* classcache_init *************************************************************
255 Initialize the class cache
257 Note: NOT synchronized!
259 *******************************************************************************/
261 bool classcache_init(void)
263 /* create the hashtable */
265 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
267 #if defined(ENABLE_THREADS)
268 /* create utf hashtable lock object */
270 lock_hashtable_classcache = NEW(java_objectheader);
272 lock_init_object_lock(lock_hashtable_classcache);
275 /* everything's ok */
280 /* classcache_new_loader_entry *************************************************
282 Create a new classcache_loader_entry struct
283 (internally used helper function)
286 loader...........the ClassLoader object
287 next.............the next classcache_loader_entry
290 the new classcache_loader_entry
292 *******************************************************************************/
294 static classcache_loader_entry * classcache_new_loader_entry(
295 classloader * loader,
296 classcache_loader_entry * next)
298 classcache_loader_entry *lden;
300 lden = NEW(classcache_loader_entry);
301 lden->loader = loader;
303 CLASSCACHE_COUNT(stat_new_loader_entry);
308 /* classcache_merge_loaders ****************************************************
310 Merge two lists of loaders into one
311 (internally used helper function)
314 lista............first list (may be NULL)
315 listb............second list (may be NULL)
318 the merged list (may be NULL)
321 The lists given as arguments are destroyed!
323 *******************************************************************************/
325 static classcache_loader_entry * classcache_merge_loaders(
326 classcache_loader_entry * lista,
327 classcache_loader_entry * listb)
329 classcache_loader_entry *result;
330 classcache_loader_entry *ldenA;
331 classcache_loader_entry *ldenB;
332 classcache_loader_entry **chain;
334 CLASSCACHE_COUNT(stat_merge_loader_entries);
336 /* XXX This is a quadratic algorithm. If this ever
337 * becomes a problem, the loader lists should be
338 * stored as sorted lists and merged in linear time. */
343 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
345 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
346 if (ldenB->loader == ldenA->loader)
350 /* this loader is only in lista */
352 chain = &(ldenA->next);
355 /* XXX free the duplicated element */
359 /* concat listb to the result */
365 /* classcache_merge_class_entries **********************************************
367 Merge two `classcache_class_entry`s into one.
368 (internally used helper function)
371 en...............the classcache_name_entry containing both class entries
372 clsenA...........first class entry, will receive the result
373 clsenB...........second class entry
376 Either both entries must have the same classobj, or one of them has
380 clsenB is freed by this function!
382 *******************************************************************************/
384 static void classcache_merge_class_entries(classcache_name_entry *en,
385 classcache_class_entry *clsenA,
386 classcache_class_entry *clsenB)
388 #ifdef CLASSCACHE_VERBOSE
389 char logbuffer[1024];
395 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
397 #ifdef CLASSCACHE_VERBOSE
398 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
399 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
400 if (clsenA->classobj)
401 utf_cat_classname(logbuffer, clsenA->classobj->name);
402 if (clsenB->classobj)
403 utf_cat_classname(logbuffer, clsenB->classobj->name);
407 CLASSCACHE_COUNT(stat_merge_class_entries);
409 /* clsenB will be merged into clsenA */
410 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
411 clsenB->loaders = NULL; /* these have been freed or reused */
413 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
414 clsenB->constraints);
415 clsenB->constraints = NULL; /* these have been freed or reused */
417 if (!clsenA->classobj)
418 clsenA->classobj = clsenB->classobj;
420 /* remove clsenB from the list of class entries */
421 classcache_remove_class_entry(en, clsenB);
425 /* classcache_lookup_name ******************************************************
427 Lookup a name in the first level of the cache
428 (internally used helper function)
431 name.............the name to look up
434 a pointer to the classcache_name_entry for this name, or
435 null if no entry was found.
437 *******************************************************************************/
439 static classcache_name_entry *classcache_lookup_name(utf *name)
441 classcache_name_entry *c; /* hash table element */
442 u4 key; /* hashkey computed from classname */
443 u4 slot; /* slot in hashtable */
445 CLASSCACHE_COUNT(stat_lookup_name);
447 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
448 slot = key & (hashtable_classcache.size - 1);
449 c = hashtable_classcache.ptr[slot];
451 /* search external hash chain for the entry */
454 /* entry found in hashtable */
455 CLASSCACHE_COUNT(stat_lookup_name_entry);
460 c = c->hashlink; /* next element in external chain */
465 CLASSCACHE_COUNT(stat_lookup_name_notfound);
470 /* classcache_new_name *********************************************************
472 Return a classcache_name_entry for the given name. The entry is created
473 if it is not already in the cache.
474 (internally used helper function)
477 name.............the name to look up / create an entry for
480 a pointer to the classcache_name_entry for this name
482 *******************************************************************************/
484 static classcache_name_entry *classcache_new_name(utf *name)
486 classcache_name_entry *c; /* hash table element */
487 u4 key; /* hashkey computed from classname */
488 u4 slot; /* slot in hashtable */
491 CLASSCACHE_COUNT(stat_lookup_new_name);
493 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
494 slot = key & (hashtable_classcache.size - 1);
495 c = hashtable_classcache.ptr[slot];
497 /* search external hash chain for the entry */
500 /* entry found in hashtable */
501 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
506 c = c->hashlink; /* next element in external chain */
509 /* location in hashtable found, create new entry */
511 c = NEW(classcache_name_entry);
516 /* insert entry into hashtable */
517 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
518 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
519 hashtable_classcache.ptr[slot] = c;
521 /* update number of hashtable-entries */
522 hashtable_classcache.entries++;
523 CLASSCACHE_COUNT(stat_classnames_stored);
525 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
526 /* reorganization of hashtable */
528 classcache_name_entry *c2;
529 hashtable newhash; /* the new hashtable */
531 CLASSCACHE_COUNT(stat_rehash_names);
533 /* create new hashtable, double the size */
535 hashtable_create(&newhash, hashtable_classcache.size * 2);
536 newhash.entries = hashtable_classcache.entries;
538 /* transfer elements to new hashtable */
540 for (i = 0; i < hashtable_classcache.size; i++) {
541 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
543 classcache_name_entry *nextc = c2->hashlink;
545 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
547 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
548 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
549 newhash.ptr[newslot] = c2;
555 /* dispose old table */
557 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
558 hashtable_classcache = newhash;
565 /* classcache_lookup ***********************************************************
567 Lookup a possibly loaded class
570 initloader.......initiating loader for resolving the class name
571 classname........class name to look up
574 The return value is a pointer to the cached class object,
575 or NULL, if the class is not in the cache.
577 Note: synchronized with global tablelock
579 *******************************************************************************/
581 classinfo *classcache_lookup(classloader *initloader, utf *classname)
583 classcache_name_entry *en;
584 classcache_class_entry *clsen;
585 classcache_loader_entry *lden;
586 classinfo *cls = NULL;
590 CLASSCACHE_COUNT(stat_lookup);
591 en = classcache_lookup_name(classname);
594 /* iterate over all class entries */
596 for (clsen = en->classes; clsen; clsen = clsen->next) {
597 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
598 /* check if this entry has been loaded by initloader */
600 for (lden = clsen->loaders; lden; lden = lden->next) {
601 CLASSCACHE_COUNT(stat_lookup_loader_checked);
602 if (lden->loader == initloader) {
603 /* found the loaded class entry */
605 assert(clsen->classobj);
606 cls = clsen->classobj;
619 /* classcache_lookup_defined ***************************************************
621 Lookup a class with the given name and defining loader
624 defloader........defining loader
625 classname........class name
628 The return value is a pointer to the cached class object,
629 or NULL, if the class is not in the cache.
631 *******************************************************************************/
633 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
635 classcache_name_entry *en;
636 classcache_class_entry *clsen;
637 classinfo *cls = NULL;
641 en = classcache_lookup_name(classname);
644 /* iterate over all class entries */
645 for (clsen = en->classes; clsen; clsen = clsen->next) {
646 if (!clsen->classobj)
649 /* check if this entry has been defined by defloader */
650 if (clsen->classobj->classloader == defloader) {
651 cls = clsen->classobj;
663 /* classcache_lookup_defined_or_initiated **************************************
665 Lookup a class that has been defined or initiated by the given loader
668 loader...........defining or initiating loader
669 classname........class name to look up
672 The return value is a pointer to the cached class object,
673 or NULL, if the class is not in the cache.
675 Note: synchronized with global tablelock
677 *******************************************************************************/
679 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
682 classcache_name_entry *en;
683 classcache_class_entry *clsen;
684 classcache_loader_entry *lden;
685 classinfo *cls = NULL;
689 en = classcache_lookup_name(classname);
692 /* iterate over all class entries */
694 for (clsen = en->classes; clsen; clsen = clsen->next) {
696 /* check if this entry has been defined by loader */
697 if (clsen->classobj && clsen->classobj->classloader == loader) {
698 cls = clsen->classobj;
702 /* check if this entry has been initiated by loader */
703 for (lden = clsen->loaders; lden; lden = lden->next) {
704 if (lden->loader == loader) {
705 /* found the loaded class entry */
707 assert(clsen->classobj);
708 cls = clsen->classobj;
721 /* classcache_store ************************************************************
723 Store a loaded class. If a class of the same name has already been stored
724 with the same initiating loader, then the given class CLS is freed (if
725 possible) and the previously stored class is returned.
728 initloader.......initiating loader used to load the class
729 (may be NULL indicating the bootstrap loader)
730 cls..............class object to cache
731 mayfree..........true if CLS may be freed in case another class is
735 cls..............everything ok, the class was stored in the cache,
736 other classinfo..another class with the same (initloader,name) has been
737 stored earlier. CLS has been freed[1] and the earlier
738 stored class is returned.
739 NULL.............an exception has been thrown.
741 Note: synchronized with global tablelock
743 [1]...in case MAYFREE is true
745 *******************************************************************************/
747 classinfo *classcache_store(classloader *initloader, classinfo *cls,
750 classcache_name_entry *en;
751 classcache_class_entry *clsen;
752 classcache_class_entry *clsenB;
753 classcache_loader_entry *lden;
754 #ifdef CLASSCACHE_VERBOSE
755 char logbuffer[1024];
759 assert(cls->state & CLASS_LOADED);
763 #ifdef CLASSCACHE_VERBOSE
764 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
765 utf_cat_classname(logbuffer, cls->name);
766 strcat(logbuffer,")");
770 en = classcache_new_name(cls->name);
774 /* iterate over all class entries */
775 for (clsen = en->classes; clsen; clsen = clsen->next) {
777 /* check if this entry has already been loaded by initloader */
778 for (lden = clsen->loaders; lden; lden = lden->next) {
779 if (lden->loader == initloader) {
780 if (clsen->classobj != cls) {
781 /* A class with the same (initloader,name) pair has been stored already. */
782 /* We free the given class and return the earlier one. */
783 #ifdef CLASSCACHE_VERBOSE
784 dolog("replacing %p with earlier loaded class %p",cls,clsen->classobj);
786 assert(clsen->classobj);
789 cls = clsen->classobj;
795 /* {This entry has not been resolved with initloader} */
797 /* check if initloader is constrained to this entry */
798 for (lden = clsen->constraints; lden; lden = lden->next) {
799 if (lden->loader == initloader) {
800 /* we have to use this entry. check if it has been resolved */
801 if (clsen->classobj) {
802 /* check if is has already been resolved to another class */
803 if (clsen->classobj != cls) {
804 /* a loading constraint is violated */
805 *exceptionptr = exceptions_new_linkageerror(
806 "loading constraint violated: ",cls);
807 goto return_exception;
810 /* record initloader as initiating loader */
811 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
815 /* {this is the first resolution for this entry} */
816 /* record initloader as initiating loader */
817 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
819 /* maybe we can merge this entry with another one */
820 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
821 /* we dont want the entry that we have already */
822 if (clsenB->classobj == cls) {
823 /* this entry has the same classobj. let's merge them */
824 classcache_merge_class_entries(en,clsen,clsenB);
829 /* record the loaded class object */
830 clsen->classobj = cls;
831 CLASSCACHE_COUNT(stat_classes_stored);
840 /* {There is no class entry containing initloader as initiating
841 * or constrained loader.} */
843 /* we look for a class entry with the same classobj we want to store */
844 for (clsen = en->classes; clsen; clsen = clsen->next) {
845 if (clsen->classobj == cls) {
846 /* this entry is about the same classobj. let's use it */
847 /* check if this entry has already been loaded by initloader */
848 for (lden = clsen->loaders; lden; lden = lden->next) {
849 if (lden->loader == initloader)
852 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
857 /* create a new class entry for this class object with */
858 /* initiating loader initloader */
860 clsen = NEW(classcache_class_entry);
861 clsen->classobj = cls;
862 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
863 clsen->constraints = NULL;
865 clsen->next = en->classes;
867 CLASSCACHE_COUNT(stat_classes_stored);
870 #ifdef CLASSCACHE_VERBOSE
871 classcache_debug_dump(stderr,cls->name);
878 return NULL; /* exception */
881 /* classcache_store_unique *****************************************************
883 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
884 aroung classcache_store that throws an exception if a class with the same
885 name has already been loaded by the bootstrap loader.
887 This function is used to register a few special classes during startup.
888 It should not be used otherwise.
891 cls..............class object to cache
894 true.............everything ok, the class was stored.
895 false............an exception has been thrown.
897 Note: synchronized with global tablelock
899 *******************************************************************************/
901 bool classcache_store_unique(classinfo *cls)
905 result = classcache_store(NULL,cls,false);
910 *exceptionptr = new_internalerror("class already stored in the class cache");
917 /* classcache_store_defined ****************************************************
919 Store a loaded class after it has been defined. If the class has already
920 been defined by the same defining loader in another thread, free the given
921 class and returned the one which has been defined earlier.
924 cls..............class object to store. classloader must be set
925 (classloader may be NULL, for bootloader)
928 cls..............everything ok, the class was stored the cache,
929 other classinfo..the class had already been defined, CLS was freed, the
930 class which was defined earlier is returned,
931 NULL.............an exception has been thrown.
933 *******************************************************************************/
935 classinfo *classcache_store_defined(classinfo *cls)
937 classcache_name_entry *en;
938 classcache_class_entry *clsen;
939 #ifdef CLASSCACHE_VERBOSE
940 char logbuffer[1024];
944 assert(cls->state & CLASS_LOADED);
948 #ifdef CLASSCACHE_VERBOSE
949 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
950 utf_cat_classname(logbuffer, cls->name);
951 strcat(logbuffer,")");
955 en = classcache_new_name(cls->name);
959 /* iterate over all class entries */
960 for (clsen = en->classes; clsen; clsen = clsen->next) {
962 /* check if this class has been defined by the same classloader */
963 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
964 /* we found an earlier definition, delete the newer one */
965 /* (if it is a different classinfo) */
966 if (clsen->classobj != cls) {
967 #ifdef CLASSCACHE_VERBOSE
968 dolog("replacing %p with earlier defined class %p",cls,clsen->classobj);
971 cls = clsen->classobj;
977 /* create a new class entry for this class object */
978 /* the list of initiating loaders is empty at this point */
980 clsen = NEW(classcache_class_entry);
981 clsen->classobj = cls;
982 clsen->loaders = NULL;
983 clsen->constraints = NULL;
985 clsen->next = en->classes;
987 CLASSCACHE_COUNT(stat_classes_stored);
990 #ifdef CLASSCACHE_VERBOSE
991 classcache_debug_dump(stderr,cls->name);
997 /* classcache_find_loader ******************************************************
999 Find the class entry loaded by or constrained to a given loader
1000 (internally used helper function)
1003 entry............the classcache_name_entry
1004 loader...........the loader to look for
1007 the classcache_class_entry for the given loader, or
1008 NULL if no entry was found
1010 *******************************************************************************/
1012 static classcache_class_entry * classcache_find_loader(
1013 classcache_name_entry * entry,
1014 classloader * loader)
1016 classcache_class_entry *clsen;
1017 classcache_loader_entry *lden;
1021 /* iterate over all class entries */
1022 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1024 /* check if this entry has already been loaded by initloader */
1025 for (lden = clsen->loaders; lden; lden = lden->next) {
1026 if (lden->loader == loader)
1027 return clsen; /* found */
1030 /* check if loader is constrained to this entry */
1031 for (lden = clsen->constraints; lden; lden = lden->next) {
1032 if (lden->loader == loader)
1033 return clsen; /* found */
1041 /* classcache_free_class_entry *************************************************
1043 Free the memory used by a class entry
1046 clsen............the classcache_class_entry to free
1048 *******************************************************************************/
1050 static void classcache_free_class_entry(classcache_class_entry * clsen)
1052 classcache_loader_entry *lden;
1053 classcache_loader_entry *next;
1057 for (lden = clsen->loaders; lden; lden = next) {
1059 FREE(lden, classcache_loader_entry);
1061 for (lden = clsen->constraints; lden; lden = next) {
1063 FREE(lden, classcache_loader_entry);
1066 FREE(clsen, classcache_class_entry);
1069 /* classcache_remove_class_entry ***********************************************
1071 Remove a classcache_class_entry from the list of possible resolution of
1073 (internally used helper function)
1076 entry............the classcache_name_entry
1077 clsen............the classcache_class_entry to remove
1079 *******************************************************************************/
1081 static void classcache_remove_class_entry(classcache_name_entry * entry,
1082 classcache_class_entry * clsen)
1084 classcache_class_entry **chain;
1089 chain = &(entry->classes);
1091 if (*chain == clsen) {
1092 *chain = clsen->next;
1093 classcache_free_class_entry(clsen);
1096 chain = &((*chain)->next);
1100 /* classcache_free_name_entry **************************************************
1102 Free the memory used by a name entry
1105 entry............the classcache_name_entry to free
1107 *******************************************************************************/
1109 static void classcache_free_name_entry(classcache_name_entry * entry)
1111 classcache_class_entry *clsen;
1112 classcache_class_entry *next;
1116 for (clsen = entry->classes; clsen; clsen = next) {
1118 classcache_free_class_entry(clsen);
1121 FREE(entry, classcache_name_entry);
1124 /* classcache_free *************************************************************
1126 Free the memory used by the class cache
1129 The class cache may not be used any more after this call, except
1130 when it is reinitialized with classcache_init.
1132 Note: NOT synchronized!
1134 *******************************************************************************/
1136 void classcache_free(void)
1139 classcache_name_entry *entry;
1140 classcache_name_entry *next;
1142 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1143 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1144 next = entry->hashlink;
1145 classcache_free_name_entry(entry);
1149 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1150 hashtable_classcache.size = 0;
1151 hashtable_classcache.entries = 0;
1152 hashtable_classcache.ptr = NULL;
1155 /* classcache_add_constraint ***************************************************
1157 Add a loading constraint
1160 a................first initiating loader
1161 b................second initiating loader
1162 classname........class name
1165 true.............everything ok, the constraint has been added,
1166 false............an exception has been thrown.
1168 Note: synchronized with global tablelock
1170 *******************************************************************************/
1172 #if defined(ENABLE_VERIFIER)
1173 bool classcache_add_constraint(classloader * a,
1177 classcache_name_entry *en;
1178 classcache_class_entry *clsenA;
1179 classcache_class_entry *clsenB;
1183 #ifdef CLASSCACHE_VERBOSE
1184 fprintf(stderr, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1185 utf_fprint_printable_ascii_classname(stderr, classname);
1186 fprintf(stderr, ")\n");
1189 /* a constraint with a == b is trivially satisfied */
1191 CLASSCACHE_COUNT(stat_trivial_constraints);
1197 en = classcache_new_name(classname);
1200 CLASSCACHE_COUNT(stat_nontriv_constraints);
1202 /* find the entry loaded by / constrained to each loader */
1203 clsenA = classcache_find_loader(en, a);
1204 clsenB = classcache_find_loader(en, b);
1206 if (clsenA && clsenB) {
1207 /* { both loaders have corresponding entries } */
1208 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1210 /* if the entries are the same, the constraint is already recorded */
1211 if (clsenA == clsenB)
1212 goto return_success;
1214 /* check if the entries can be merged */
1215 if (clsenA->classobj && clsenB->classobj
1216 && clsenA->classobj != clsenB->classobj) {
1217 /* no, the constraint is violated */
1218 *exceptionptr = exceptions_new_linkageerror(
1219 "loading constraint violated: ",clsenA->classobj);
1220 goto return_exception;
1223 /* yes, merge the entries */
1224 classcache_merge_class_entries(en,clsenA,clsenB);
1225 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1228 /* { at most one of the loaders has a corresponding entry } */
1230 /* set clsenA to the single class entry we have */
1235 /* { no loader has a corresponding entry } */
1236 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1238 /* create a new class entry with the constraint (a,b,en->name) */
1239 clsenA = NEW(classcache_class_entry);
1240 clsenA->classobj = NULL;
1241 clsenA->loaders = NULL;
1242 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1243 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1245 clsenA->next = en->classes;
1246 en->classes = clsenA;
1249 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1251 /* make b the loader that has no corresponding entry */
1255 /* loader b must be added to entry clsenA */
1256 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1261 CLASSCACHE_UNLOCK();
1265 CLASSCACHE_UNLOCK();
1266 return false; /* exception */
1268 #endif /* defined(ENABLE_VERIFIER) */
1270 /* classcache_add_constraints_for_params ***************************************
1272 Add loading constraints for the parameters and return type of
1276 a................first initiating loader
1277 b................second initiating loader
1278 m................methodinfo
1281 true.............everything ok, the constraints have been added,
1282 false............an exception has been thrown.
1284 Note: synchronized with global tablelock
1286 *******************************************************************************/
1288 #if defined(ENABLE_VERIFIER)
1289 bool classcache_add_constraints_for_params(classloader * a,
1297 /* a constraint with a == b is trivially satisfied */
1303 /* get the parsed descriptor */
1309 /* constrain the return type */
1311 if (md->returntype.type == TYPE_ADR) {
1312 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1313 return false; /* exception */
1316 /* constrain each reference type used in the parameters */
1318 td = md->paramtypes;
1321 if (td->type != TYPE_ADR)
1324 if (!classcache_add_constraint(a, b, td->classref->name))
1325 return false; /* exception */
1331 #endif /* defined(ENABLE_VERIFIER) */
1334 /* classcache_number_of_loaded_classes *****************************************
1336 Counts the number of loaded classes and returns it.
1338 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1341 *******************************************************************************/
1343 static s4 classcache_number_of_loaded_classes(void)
1345 classcache_name_entry *en;
1346 classcache_class_entry *clsen;
1350 /* initialize class counter */
1354 for (i = 0; i < hashtable_classcache.size; i++) {
1355 /* iterate over hashlink */
1357 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1358 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1360 if (en->name->text[0] == '$')
1363 /* iterate over classes with same name */
1365 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1366 /* get only loaded classes */
1368 if (clsen->classobj != NULL)
1378 /* classcache_get_loaded_class_count *******************************************
1380 Counts the number of loaded classes and returns it.
1382 *******************************************************************************/
1384 s4 classcache_get_loaded_class_count(void)
1390 count = classcache_number_of_loaded_classes();
1392 CLASSCACHE_UNLOCK();
1398 /* classcache_get_loaded_classes ***********************************************
1400 Returns an array of all loaded classes as array. The array is
1401 allocaed on the Java heap.
1403 *******************************************************************************/
1405 #if defined(ENABLE_JVMTI)
1406 void classcache_get_loaded_classes(s4 *class_count_ptr,
1407 classinfo ***classes_ptr)
1409 classinfo **classes;
1411 classcache_name_entry *en;
1412 classcache_class_entry *clsen;
1418 /* get the number of loaded classes and allocate the array */
1420 class_count = classcache_number_of_loaded_classes();
1422 classes = GCMNEW(classinfo*, class_count);
1424 /* look in every slot of the hashtable */
1426 for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1427 /* iterate over hashlink */
1429 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1430 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1432 if (en->name->text[0] == '$')
1435 /* iterate over classes with same name */
1437 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1438 /* get only loaded classes */
1440 if (clsen->classobj != NULL) {
1441 classes[j] = clsen->classobj;
1448 /* pass the return values */
1450 *class_count_ptr = class_count;
1451 *classes_ptr = classes;
1453 CLASSCACHE_UNLOCK();
1455 #endif /* defined(ENABLE_JVMTI) */
1458 /*============================================================================*/
1460 /*============================================================================*/
1462 /* classcache_debug_dump *******************************************************
1464 Print the contents of the loaded class cache to a stream
1467 file.............output stream
1468 only.............if != NULL, only print entries for this name
1469 (Currently we print also the rest of the hash chain to
1470 get a feel for the average length of hash chains.)
1472 Note: synchronized with global tablelock
1474 *******************************************************************************/
1477 void classcache_debug_dump(FILE * file,utf *only)
1479 classcache_name_entry *c;
1480 classcache_class_entry *clsen;
1481 classcache_loader_entry *lden;
1486 fprintf(file, "\n=== [loaded class cache] =====================================\n\n");
1487 fprintf(file, "hash size : %d\n", (int) hashtable_classcache.size);
1488 fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries);
1489 fprintf(file, "\n");
1492 c = classcache_lookup_name(only);
1493 slot = 0; /* avoid compiler warning */
1497 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1498 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1501 for (; c; c = c->hashlink) {
1502 utf_fprint_printable_ascii_classname(file, c->name);
1503 fprintf(file, "\n");
1505 /* iterate over all class entries */
1506 for (clsen = c->classes; clsen; clsen = clsen->next) {
1507 if (clsen->classobj) {
1508 fprintf(file, " loaded %p\n", (void *) clsen->classobj);
1511 fprintf(file, " unresolved\n");
1513 fprintf(file, " loaders:");
1514 for (lden = clsen->loaders; lden; lden = lden->next) {
1515 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1517 fprintf(file, "\n constraints:");
1518 for (lden = clsen->constraints; lden; lden = lden->next) {
1519 fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1521 fprintf(file, "\n");
1528 fprintf(file, "\n==============================================================\n\n");
1530 CLASSCACHE_UNLOCK();
1535 * These are local overrides for various environment variables in Emacs.
1536 * Please do not remove this and leave it at the end of the file, where
1537 * Emacs will automagically detect them.
1538 * ---------------------------------------------------------------------
1541 * indent-tabs-mode: t
1545 * vim:noexpandtab:sw=4:ts=4: