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
34 #include "mm/memory.h"
36 #include "threads/lock-common.h"
38 #include "toolbox/hashtable.h"
39 #include "toolbox/logging.h"
41 #include "vm/exceptions.h"
43 #include "vmcore/classcache.h"
44 #include "vmcore/utf8.h"
47 /*************************************************************************
51 The classcache has two functions:
53 1) caching the resolution of class references
54 2) storing and checking loading constraints
56 We will use the following terms in this description:
58 N a class name: a utf string
59 (N,L) a class reference with initiating loader L and class name N
60 C a class (object): the result of resolving a reference (N,L)
61 We will write resultion as
63 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
64 resolve to the same class C. So (N,L1,L2) means
67 The functions of the classcache require:
69 1) a mapping (N,L) |--> C for looking up prior resolution results.
70 2) storing the current set of loading constraints { (N,L1,L2) }
72 These functions can be rearranged like that:
74 a mapping N |--> (a mapping L |--> C or NULL,
75 a set of constraints {(L1,L2)})
77 Thus we can treat the mapping and constraints for each name N
78 separately. The implementation does this by keeping a hash table
79 mapping a name N to a `classcache_name_entry` which contains all
80 info with respect to N.
82 For a class name N we can define an equivalence relation ~N~ on
85 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
87 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
89 Also, if two references (N,L1) and (N,L2) resolve to the same class C
90 we have L1 ~N~ L2 because class loaders are required to return
91 consistent resolutions for a name N [XXX].
93 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
95 Cx...is a class C or NULL
96 IL...is the set of initiating loaders
97 CL...is the set of constrained loaders
99 Such a tuple is called `classcache_class_entry` in the source code.
101 The following holds for each tuple (Cx,IL,CL):
103 . (Cx is NULL) implies IL = {}.
105 . If Cx is a class, IL is the set of loaders that have been
106 recorded as initiating loaders for Cx. IL may be the
107 empty set {} in case Cx has already been defined but no
108 initiating loader has been recorded, yet.
110 . (IL u CL) is a subset of an equivalence class of ~N~.
112 (This means that all loaders in IL and CL must resolve
113 the name N to the same class.)
115 The following holds for the set of tuples { (Cx,IL,CL) }:
117 . For a given class C there is at most one tuple with Cx = C
118 in the set. (There may be an arbitrary number of tuples
119 with Cx = NULL, however.)
121 . For a given loader L there is at most one tuple with
124 The implementation stores sets of loaders as linked lists of
125 `classcache_loader_entry`s.
127 Comments about manipulating the classcache can be found in the
128 individual functions below.
130 *************************************************************************/
133 /* initial number of slots in the classcache hash table */
134 #define CLASSCACHE_INIT_SIZE 2048
136 /*============================================================================*/
138 /*============================================================================*/
140 /* #define CLASSCACHE_VERBOSE */
142 /*============================================================================*/
144 /*============================================================================*/
146 /*#define CLASSCACHE_STATS*/
148 #ifdef CLASSCACHE_STATS
149 static int stat_classnames_stored = 0;
150 static int stat_classes_stored = 0;
151 static int stat_trivial_constraints = 0;
152 static int stat_nontriv_constraints = 0;
153 static int stat_nontriv_constraints_both = 0;
154 static int stat_nontriv_constraints_merged = 0;
155 static int stat_nontriv_constraints_one = 0;
156 static int stat_nontriv_constraints_none = 0;
157 static int stat_new_loader_entry = 0;
158 static int stat_merge_class_entries = 0;
159 static int stat_merge_loader_entries = 0;
160 static int stat_lookup = 0;
161 static int stat_lookup_class_entry_checked = 0;
162 static int stat_lookup_loader_checked = 0;
163 static int stat_lookup_name = 0;
164 static int stat_lookup_name_entry = 0;
165 static int stat_lookup_name_notfound = 0;
166 static int stat_lookup_new_name = 0;
167 static int stat_lookup_new_name_entry = 0;
168 static int stat_lookup_new_name_collisions = 0;
169 static int stat_rehash_names = 0;
170 static int stat_rehash_names_collisions = 0;
172 #define CLASSCACHE_COUNT(cnt) (cnt)++
173 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
175 void classcache_print_statistics(FILE *file) {
176 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
177 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
178 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
179 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
180 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
181 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
182 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
183 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
184 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
185 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
186 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
187 fprintf(file,"lookups : %8d\n",stat_lookup);
188 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
189 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
190 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
191 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
192 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
193 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
194 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
195 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
196 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
197 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
200 #define CLASSCACHE_COUNT(cnt)
201 #define CLASSCACHE_COUNTIF(cond,cnt)
204 /*============================================================================*/
205 /* THREAD-SAFE LOCKING */
206 /*============================================================================*/
208 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
209 /* CAUTION: The static functions below are */
210 /* NOT synchronized! */
211 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
213 #if defined(ENABLE_THREADS)
214 # define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
215 # define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
217 # define CLASSCACHE_LOCK()
218 # define CLASSCACHE_UNLOCK()
221 /*============================================================================*/
222 /* GLOBAL VARIABLES */
223 /*============================================================================*/
225 hashtable hashtable_classcache;
227 #if defined(ENABLE_THREADS)
228 static java_object_t *lock_hashtable_classcache;
232 /*============================================================================*/
234 /*============================================================================*/
238 static void classcache_free_class_entry(classcache_class_entry *clsen);
239 static void classcache_remove_class_entry(classcache_name_entry *en,
240 classcache_class_entry *clsen);
242 /* hash function to use */
244 #define CLASSCACHE_HASH utf_full_hashkey
246 /* classcache_init *************************************************************
248 Initialize the class cache
250 Note: NOT synchronized!
252 *******************************************************************************/
254 bool classcache_init(void)
256 /* create the hashtable */
258 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
260 #if defined(ENABLE_THREADS)
261 /* create utf hashtable lock object */
263 lock_hashtable_classcache = NEW(java_object_t);
265 LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
268 /* everything's ok */
273 /* classcache_new_loader_entry *************************************************
275 Create a new classcache_loader_entry struct
276 (internally used helper function)
279 loader...........the ClassLoader object
280 next.............the next classcache_loader_entry
283 the new classcache_loader_entry
285 *******************************************************************************/
287 static classcache_loader_entry * classcache_new_loader_entry(
288 classloader * loader,
289 classcache_loader_entry * next)
291 classcache_loader_entry *lden;
293 lden = NEW(classcache_loader_entry);
294 lden->loader = loader;
296 CLASSCACHE_COUNT(stat_new_loader_entry);
301 /* classcache_merge_loaders ****************************************************
303 Merge two lists of loaders into one
304 (internally used helper function)
307 lista............first list (may be NULL)
308 listb............second list (may be NULL)
311 the merged list (may be NULL)
314 The lists given as arguments are destroyed!
316 *******************************************************************************/
318 static classcache_loader_entry * classcache_merge_loaders(
319 classcache_loader_entry * lista,
320 classcache_loader_entry * listb)
322 classcache_loader_entry *result;
323 classcache_loader_entry *ldenA;
324 classcache_loader_entry *ldenB;
325 classcache_loader_entry **chain;
327 CLASSCACHE_COUNT(stat_merge_loader_entries);
329 /* XXX This is a quadratic algorithm. If this ever
330 * becomes a problem, the loader lists should be
331 * stored as sorted lists and merged in linear time. */
336 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
338 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
339 if (ldenB->loader == ldenA->loader)
343 /* this loader is only in lista */
345 chain = &(ldenA->next);
348 /* XXX free the duplicated element */
352 /* concat listb to the result */
358 /* classcache_merge_class_entries **********************************************
360 Merge two `classcache_class_entry`s into one.
361 (internally used helper function)
364 en...............the classcache_name_entry containing both class entries
365 clsenA...........first class entry, will receive the result
366 clsenB...........second class entry
369 Either both entries must have the same classobj, or one of them has
373 clsenB is freed by this function!
375 *******************************************************************************/
377 static void classcache_merge_class_entries(classcache_name_entry *en,
378 classcache_class_entry *clsenA,
379 classcache_class_entry *clsenB)
381 #ifdef CLASSCACHE_VERBOSE
382 char logbuffer[1024];
388 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
390 #ifdef CLASSCACHE_VERBOSE
391 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
392 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
393 if (clsenA->classobj)
394 utf_cat_classname(logbuffer, clsenA->classobj->name);
395 if (clsenB->classobj)
396 utf_cat_classname(logbuffer, clsenB->classobj->name);
397 log_println(logbuffer);
400 CLASSCACHE_COUNT(stat_merge_class_entries);
402 /* clsenB will be merged into clsenA */
403 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
404 clsenB->loaders = NULL; /* these have been freed or reused */
406 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
407 clsenB->constraints);
408 clsenB->constraints = NULL; /* these have been freed or reused */
410 if (!clsenA->classobj)
411 clsenA->classobj = clsenB->classobj;
413 /* remove clsenB from the list of class entries */
414 classcache_remove_class_entry(en, clsenB);
418 /* classcache_lookup_name ******************************************************
420 Lookup a name in the first level of the cache
421 (internally used helper function)
424 name.............the name to look up
427 a pointer to the classcache_name_entry for this name, or
428 null if no entry was found.
430 *******************************************************************************/
432 static classcache_name_entry *classcache_lookup_name(utf *name)
434 classcache_name_entry *c; /* hash table element */
435 u4 key; /* hashkey computed from classname */
436 u4 slot; /* slot in hashtable */
438 CLASSCACHE_COUNT(stat_lookup_name);
440 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
441 slot = key & (hashtable_classcache.size - 1);
442 c = hashtable_classcache.ptr[slot];
444 /* search external hash chain for the entry */
447 /* entry found in hashtable */
448 CLASSCACHE_COUNT(stat_lookup_name_entry);
453 c = c->hashlink; /* next element in external chain */
458 CLASSCACHE_COUNT(stat_lookup_name_notfound);
463 /* classcache_new_name *********************************************************
465 Return a classcache_name_entry for the given name. The entry is created
466 if it is not already in the cache.
467 (internally used helper function)
470 name.............the name to look up / create an entry for
473 a pointer to the classcache_name_entry for this name
475 *******************************************************************************/
477 static classcache_name_entry *classcache_new_name(utf *name)
479 classcache_name_entry *c; /* hash table element */
480 u4 key; /* hashkey computed from classname */
481 u4 slot; /* slot in hashtable */
484 CLASSCACHE_COUNT(stat_lookup_new_name);
486 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
487 slot = key & (hashtable_classcache.size - 1);
488 c = hashtable_classcache.ptr[slot];
490 /* search external hash chain for the entry */
493 /* entry found in hashtable */
494 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
499 c = c->hashlink; /* next element in external chain */
502 /* location in hashtable found, create new entry */
504 c = NEW(classcache_name_entry);
509 /* insert entry into hashtable */
510 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
511 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
512 hashtable_classcache.ptr[slot] = c;
514 /* update number of hashtable-entries */
515 hashtable_classcache.entries++;
516 CLASSCACHE_COUNT(stat_classnames_stored);
518 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
519 /* reorganization of hashtable */
521 classcache_name_entry *c2;
522 hashtable newhash; /* the new hashtable */
524 CLASSCACHE_COUNT(stat_rehash_names);
526 /* create new hashtable, double the size */
528 hashtable_create(&newhash, hashtable_classcache.size * 2);
529 newhash.entries = hashtable_classcache.entries;
531 /* transfer elements to new hashtable */
533 for (i = 0; i < hashtable_classcache.size; i++) {
534 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
536 classcache_name_entry *nextc = c2->hashlink;
538 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
540 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
541 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
542 newhash.ptr[newslot] = c2;
548 /* dispose old table */
550 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
551 hashtable_classcache = newhash;
558 /* classcache_lookup ***********************************************************
560 Lookup a possibly loaded class
563 initloader.......initiating loader for resolving the class name
564 classname........class name to look up
567 The return value is a pointer to the cached class object,
568 or NULL, if the class is not in the cache.
570 Note: synchronized with global tablelock
572 *******************************************************************************/
574 classinfo *classcache_lookup(classloader *initloader, utf *classname)
576 classcache_name_entry *en;
577 classcache_class_entry *clsen;
578 classcache_loader_entry *lden;
579 classinfo *cls = NULL;
583 CLASSCACHE_COUNT(stat_lookup);
584 en = classcache_lookup_name(classname);
587 /* iterate over all class entries */
589 for (clsen = en->classes; clsen; clsen = clsen->next) {
590 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
591 /* check if this entry has been loaded by initloader */
593 for (lden = clsen->loaders; lden; lden = lden->next) {
594 CLASSCACHE_COUNT(stat_lookup_loader_checked);
595 if (lden->loader == initloader) {
596 /* found the loaded class entry */
598 assert(clsen->classobj);
599 cls = clsen->classobj;
612 /* classcache_lookup_defined ***************************************************
614 Lookup a class with the given name and defining loader
617 defloader........defining loader
618 classname........class name
621 The return value is a pointer to the cached class object,
622 or NULL, if the class is not in the cache.
624 *******************************************************************************/
626 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
628 classcache_name_entry *en;
629 classcache_class_entry *clsen;
630 classinfo *cls = NULL;
634 en = classcache_lookup_name(classname);
637 /* iterate over all class entries */
638 for (clsen = en->classes; clsen; clsen = clsen->next) {
639 if (!clsen->classobj)
642 /* check if this entry has been defined by defloader */
643 if (clsen->classobj->classloader == defloader) {
644 cls = clsen->classobj;
656 /* classcache_lookup_defined_or_initiated **************************************
658 Lookup a class that has been defined or initiated by the given loader
661 loader...........defining or initiating loader
662 classname........class name to look up
665 The return value is a pointer to the cached class object,
666 or NULL, if the class is not in the cache.
668 Note: synchronized with global tablelock
670 *******************************************************************************/
672 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
675 classcache_name_entry *en;
676 classcache_class_entry *clsen;
677 classcache_loader_entry *lden;
678 classinfo *cls = NULL;
682 en = classcache_lookup_name(classname);
685 /* iterate over all class entries */
687 for (clsen = en->classes; clsen; clsen = clsen->next) {
689 /* check if this entry has been defined by loader */
690 if (clsen->classobj && clsen->classobj->classloader == loader) {
691 cls = clsen->classobj;
695 /* check if this entry has been initiated by loader */
696 for (lden = clsen->loaders; lden; lden = lden->next) {
697 if (lden->loader == loader) {
698 /* found the loaded class entry */
700 assert(clsen->classobj);
701 cls = clsen->classobj;
714 /* classcache_store ************************************************************
716 Store a loaded class. If a class of the same name has already been stored
717 with the same initiating loader, then the given class CLS is freed (if
718 possible) and the previously stored class is returned.
721 initloader.......initiating loader used to load the class
722 (may be NULL indicating the bootstrap loader)
723 cls..............class object to cache
724 mayfree..........true if CLS may be freed in case another class is
728 cls..............everything ok, the class was stored in the cache,
729 other classinfo..another class with the same (initloader,name) has been
730 stored earlier. CLS has been freed[1] and the earlier
731 stored class is returned.
732 NULL.............an exception has been thrown.
734 Note: synchronized with global tablelock
736 [1]...in case MAYFREE is true
738 *******************************************************************************/
740 classinfo *classcache_store(classloader *initloader, classinfo *cls,
743 classcache_name_entry *en;
744 classcache_class_entry *clsen;
745 classcache_class_entry *clsenB;
746 classcache_loader_entry *lden;
747 #ifdef CLASSCACHE_VERBOSE
748 char logbuffer[1024];
752 assert(cls->state & CLASS_LOADED);
756 #ifdef CLASSCACHE_VERBOSE
757 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
758 utf_cat_classname(logbuffer, cls->name);
759 strcat(logbuffer,")");
760 log_println(logbuffer);
763 en = classcache_new_name(cls->name);
767 /* iterate over all class entries */
768 for (clsen = en->classes; clsen; clsen = clsen->next) {
770 /* check if this entry has already been loaded by initloader */
771 for (lden = clsen->loaders; lden; lden = lden->next) {
772 if (lden->loader == initloader) {
773 if (clsen->classobj != cls) {
774 /* A class with the same (initloader,name) pair has been stored already. */
775 /* We free the given class and return the earlier one. */
776 #ifdef CLASSCACHE_VERBOSE
777 log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
779 assert(clsen->classobj);
782 cls = clsen->classobj;
788 /* {This entry has not been resolved with initloader} */
790 /* check if initloader is constrained to this entry */
791 for (lden = clsen->constraints; lden; lden = lden->next) {
792 if (lden->loader == initloader) {
793 /* we have to use this entry. check if it has been resolved */
794 if (clsen->classobj) {
795 /* check if is has already been resolved to another class */
796 if (clsen->classobj != cls) {
797 /* a loading constraint is violated */
798 exceptions_throw_linkageerror("loading constraint violated: ", cls);
799 goto return_exception;
802 /* record initloader as initiating loader */
803 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
807 /* {this is the first resolution for this entry} */
808 /* record initloader as initiating loader */
809 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
811 /* maybe we can merge this entry with another one */
812 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
813 /* we dont want the entry that we have already */
814 if (clsenB->classobj == cls) {
815 /* this entry has the same classobj. let's merge them */
816 classcache_merge_class_entries(en,clsen,clsenB);
821 /* record the loaded class object */
822 clsen->classobj = cls;
823 CLASSCACHE_COUNT(stat_classes_stored);
832 /* {There is no class entry containing initloader as initiating
833 * or constrained loader.} */
835 /* we look for a class entry with the same classobj we want to store */
836 for (clsen = en->classes; clsen; clsen = clsen->next) {
837 if (clsen->classobj == cls) {
838 /* this entry is about the same classobj. let's use it */
839 /* check if this entry has already been loaded by initloader */
840 for (lden = clsen->loaders; lden; lden = lden->next) {
841 if (lden->loader == initloader)
844 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
849 /* create a new class entry for this class object with */
850 /* initiating loader initloader */
852 clsen = NEW(classcache_class_entry);
853 clsen->classobj = cls;
854 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
855 clsen->constraints = NULL;
857 clsen->next = en->classes;
859 CLASSCACHE_COUNT(stat_classes_stored);
862 #ifdef CLASSCACHE_VERBOSE
863 classcache_debug_dump(stdout,cls->name);
870 return NULL; /* exception */
873 /* classcache_store_unique *****************************************************
875 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
876 aroung classcache_store that throws an exception if a class with the same
877 name has already been loaded by the bootstrap loader.
879 This function is used to register a few special classes during startup.
880 It should not be used otherwise.
883 cls..............class object to cache
886 true.............everything ok, the class was stored.
887 false............an exception has been thrown.
889 Note: synchronized with global tablelock
891 *******************************************************************************/
893 bool classcache_store_unique(classinfo *cls)
897 result = classcache_store(NULL,cls,false);
902 exceptions_throw_internalerror("class already stored in the class cache");
909 /* classcache_store_defined ****************************************************
911 Store a loaded class after it has been defined. If the class has already
912 been defined by the same defining loader in another thread, free the given
913 class and returned the one which has been defined earlier.
916 cls..............class object to store. classloader must be set
917 (classloader may be NULL, for bootloader)
920 cls..............everything ok, the class was stored the cache,
921 other classinfo..the class had already been defined, CLS was freed, the
922 class which was defined earlier is returned,
923 NULL.............an exception has been thrown.
925 *******************************************************************************/
927 classinfo *classcache_store_defined(classinfo *cls)
929 classcache_name_entry *en;
930 classcache_class_entry *clsen;
931 #ifdef CLASSCACHE_VERBOSE
932 char logbuffer[1024];
936 assert(cls->state & CLASS_LOADED);
940 #ifdef CLASSCACHE_VERBOSE
941 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
942 utf_cat_classname(logbuffer, cls->name);
943 strcat(logbuffer,")");
944 log_println(logbuffer);
947 en = classcache_new_name(cls->name);
951 /* iterate over all class entries */
952 for (clsen = en->classes; clsen; clsen = clsen->next) {
954 /* check if this class has been defined by the same classloader */
955 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
956 /* we found an earlier definition, delete the newer one */
957 /* (if it is a different classinfo) */
958 if (clsen->classobj != cls) {
959 #ifdef CLASSCACHE_VERBOSE
960 log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
963 cls = clsen->classobj;
969 /* create a new class entry for this class object */
970 /* the list of initiating loaders is empty at this point */
972 clsen = NEW(classcache_class_entry);
973 clsen->classobj = cls;
974 clsen->loaders = NULL;
975 clsen->constraints = NULL;
977 clsen->next = en->classes;
979 CLASSCACHE_COUNT(stat_classes_stored);
982 #ifdef CLASSCACHE_VERBOSE
983 classcache_debug_dump(stdout,cls->name);
989 /* classcache_find_loader ******************************************************
991 Find the class entry loaded by or constrained to a given loader
992 (internally used helper function)
995 entry............the classcache_name_entry
996 loader...........the loader to look for
999 the classcache_class_entry for the given loader, or
1000 NULL if no entry was found
1002 *******************************************************************************/
1004 static classcache_class_entry * classcache_find_loader(
1005 classcache_name_entry * entry,
1006 classloader * loader)
1008 classcache_class_entry *clsen;
1009 classcache_loader_entry *lden;
1013 /* iterate over all class entries */
1014 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1016 /* check if this entry has already been loaded by initloader */
1017 for (lden = clsen->loaders; lden; lden = lden->next) {
1018 if (lden->loader == loader)
1019 return clsen; /* found */
1022 /* check if loader is constrained to this entry */
1023 for (lden = clsen->constraints; lden; lden = lden->next) {
1024 if (lden->loader == loader)
1025 return clsen; /* found */
1033 /* classcache_free_class_entry *************************************************
1035 Free the memory used by a class entry
1038 clsen............the classcache_class_entry to free
1040 *******************************************************************************/
1042 static void classcache_free_class_entry(classcache_class_entry * clsen)
1044 classcache_loader_entry *lden;
1045 classcache_loader_entry *next;
1049 for (lden = clsen->loaders; lden; lden = next) {
1051 FREE(lden, classcache_loader_entry);
1053 for (lden = clsen->constraints; lden; lden = next) {
1055 FREE(lden, classcache_loader_entry);
1058 FREE(clsen, classcache_class_entry);
1061 /* classcache_remove_class_entry ***********************************************
1063 Remove a classcache_class_entry from the list of possible resolution of
1065 (internally used helper function)
1068 entry............the classcache_name_entry
1069 clsen............the classcache_class_entry to remove
1071 *******************************************************************************/
1073 static void classcache_remove_class_entry(classcache_name_entry * entry,
1074 classcache_class_entry * clsen)
1076 classcache_class_entry **chain;
1081 chain = &(entry->classes);
1083 if (*chain == clsen) {
1084 *chain = clsen->next;
1085 classcache_free_class_entry(clsen);
1088 chain = &((*chain)->next);
1092 /* classcache_free_name_entry **************************************************
1094 Free the memory used by a name entry
1097 entry............the classcache_name_entry to free
1099 *******************************************************************************/
1101 static void classcache_free_name_entry(classcache_name_entry * entry)
1103 classcache_class_entry *clsen;
1104 classcache_class_entry *next;
1108 for (clsen = entry->classes; clsen; clsen = next) {
1110 classcache_free_class_entry(clsen);
1113 FREE(entry, classcache_name_entry);
1116 /* classcache_free *************************************************************
1118 Free the memory used by the class cache
1121 The class cache may not be used any more after this call, except
1122 when it is reinitialized with classcache_init.
1124 Note: NOT synchronized!
1126 *******************************************************************************/
1128 void classcache_free(void)
1131 classcache_name_entry *entry;
1132 classcache_name_entry *next;
1134 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1135 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1136 next = entry->hashlink;
1137 classcache_free_name_entry(entry);
1141 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1142 hashtable_classcache.size = 0;
1143 hashtable_classcache.entries = 0;
1144 hashtable_classcache.ptr = NULL;
1147 /* classcache_add_constraint ***************************************************
1149 Add a loading constraint
1152 a................first initiating loader
1153 b................second initiating loader
1154 classname........class name
1157 true.............everything ok, the constraint has been added,
1158 false............an exception has been thrown.
1160 Note: synchronized with global tablelock
1162 *******************************************************************************/
1164 #if defined(ENABLE_VERIFIER)
1165 bool classcache_add_constraint(classloader * a,
1169 classcache_name_entry *en;
1170 classcache_class_entry *clsenA;
1171 classcache_class_entry *clsenB;
1175 #ifdef CLASSCACHE_VERBOSE
1177 log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1178 utf_fprint_printable_ascii_classname(stdout, classname);
1183 /* a constraint with a == b is trivially satisfied */
1185 CLASSCACHE_COUNT(stat_trivial_constraints);
1191 en = classcache_new_name(classname);
1194 CLASSCACHE_COUNT(stat_nontriv_constraints);
1196 /* find the entry loaded by / constrained to each loader */
1197 clsenA = classcache_find_loader(en, a);
1198 clsenB = classcache_find_loader(en, b);
1200 if (clsenA && clsenB) {
1201 /* { both loaders have corresponding entries } */
1202 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1204 /* if the entries are the same, the constraint is already recorded */
1205 if (clsenA == clsenB)
1206 goto return_success;
1208 /* check if the entries can be merged */
1209 if (clsenA->classobj && clsenB->classobj
1210 && clsenA->classobj != clsenB->classobj) {
1211 /* no, the constraint is violated */
1212 exceptions_throw_linkageerror("loading constraint violated: ",
1214 goto return_exception;
1217 /* yes, merge the entries */
1218 classcache_merge_class_entries(en,clsenA,clsenB);
1219 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1222 /* { at most one of the loaders has a corresponding entry } */
1224 /* set clsenA to the single class entry we have */
1229 /* { no loader has a corresponding entry } */
1230 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1232 /* create a new class entry with the constraint (a,b,en->name) */
1233 clsenA = NEW(classcache_class_entry);
1234 clsenA->classobj = NULL;
1235 clsenA->loaders = NULL;
1236 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1237 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1239 clsenA->next = en->classes;
1240 en->classes = clsenA;
1243 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1245 /* make b the loader that has no corresponding entry */
1249 /* loader b must be added to entry clsenA */
1250 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1255 CLASSCACHE_UNLOCK();
1259 CLASSCACHE_UNLOCK();
1260 return false; /* exception */
1262 #endif /* defined(ENABLE_VERIFIER) */
1264 /* classcache_add_constraints_for_params ***************************************
1266 Add loading constraints for the parameters and return type of
1270 a................first initiating loader
1271 b................second initiating loader
1272 m................methodinfo
1275 true.............everything ok, the constraints have been added,
1276 false............an exception has been thrown.
1278 Note: synchronized with global tablelock
1280 *******************************************************************************/
1282 #if defined(ENABLE_VERIFIER)
1283 bool classcache_add_constraints_for_params(classloader * a,
1291 /* a constraint with a == b is trivially satisfied */
1297 /* get the parsed descriptor */
1303 /* constrain the return type */
1305 if (md->returntype.type == TYPE_ADR) {
1306 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1307 return false; /* exception */
1310 /* constrain each reference type used in the parameters */
1312 td = md->paramtypes;
1315 if (td->type != TYPE_ADR)
1318 if (!classcache_add_constraint(a, b, td->classref->name))
1319 return false; /* exception */
1325 #endif /* defined(ENABLE_VERIFIER) */
1328 /* classcache_number_of_loaded_classes *****************************************
1330 Counts the number of loaded classes and returns it.
1332 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1335 *******************************************************************************/
1337 static s4 classcache_number_of_loaded_classes(void)
1339 classcache_name_entry *en;
1340 classcache_class_entry *clsen;
1344 /* initialize class counter */
1348 for (i = 0; i < hashtable_classcache.size; i++) {
1349 /* iterate over hashlink */
1351 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1352 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1354 if (en->name->text[0] == '$')
1357 /* iterate over classes with same name */
1359 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1360 /* get only loaded classes */
1362 if (clsen->classobj != NULL)
1372 /* classcache_get_loaded_class_count *******************************************
1374 Counts the number of loaded classes and returns it.
1376 *******************************************************************************/
1378 s4 classcache_get_loaded_class_count(void)
1384 count = classcache_number_of_loaded_classes();
1386 CLASSCACHE_UNLOCK();
1392 /* classcache_get_loaded_classes ***********************************************
1394 Returns an array of all loaded classes as array. The array is
1395 allocaed on the Java heap.
1397 *******************************************************************************/
1399 #if defined(ENABLE_JVMTI)
1400 void classcache_get_loaded_classes(s4 *class_count_ptr,
1401 classinfo ***classes_ptr)
1403 classinfo **classes;
1405 classcache_name_entry *en;
1406 classcache_class_entry *clsen;
1412 /* get the number of loaded classes and allocate the array */
1414 class_count = classcache_number_of_loaded_classes();
1416 classes = GCMNEW(classinfo*, class_count);
1418 /* look in every slot of the hashtable */
1420 for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1421 /* iterate over hashlink */
1423 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1424 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1426 if (en->name->text[0] == '$')
1429 /* iterate over classes with same name */
1431 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1432 /* get only loaded classes */
1434 if (clsen->classobj != NULL) {
1435 classes[j] = clsen->classobj;
1442 /* pass the return values */
1444 *class_count_ptr = class_count;
1445 *classes_ptr = classes;
1447 CLASSCACHE_UNLOCK();
1449 #endif /* defined(ENABLE_JVMTI) */
1452 /* classcache_foreach_loaded_class *********************************************
1454 Calls the given function for each loaded class.
1456 *******************************************************************************/
1458 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1461 classcache_name_entry *en;
1462 classcache_class_entry *clsen;
1467 /* look in every slot of the hashtable */
1469 for (i = 0; i < hashtable_classcache.size; i++) {
1470 /* iterate over hashlink */
1472 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1473 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1475 if (en->name->text[0] == '$')
1478 /* iterate over classes with same name */
1480 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1481 /* get only loaded classes */
1483 if (clsen->classobj != NULL) {
1484 (*func)(clsen->classobj, data);
1490 CLASSCACHE_UNLOCK();
1494 /*============================================================================*/
1496 /*============================================================================*/
1498 /* classcache_debug_dump *******************************************************
1500 Print the contents of the loaded class cache to a stream
1503 file.............output stream
1504 only.............if != NULL, only print entries for this name
1505 (Currently we print also the rest of the hash chain to
1506 get a feel for the average length of hash chains.)
1508 Note: synchronized with global tablelock
1510 *******************************************************************************/
1513 void classcache_debug_dump(FILE * file,utf *only)
1515 classcache_name_entry *c;
1516 classcache_class_entry *clsen;
1517 classcache_loader_entry *lden;
1522 log_println("=== [loaded class cache] =====================================");
1523 log_println("hash size : %d", (int) hashtable_classcache.size);
1524 log_println("hash entries: %d", (int) hashtable_classcache.entries);
1528 c = classcache_lookup_name(only);
1529 slot = 0; /* avoid compiler warning */
1533 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1534 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1537 for (; c; c = c->hashlink) {
1538 utf_fprint_printable_ascii_classname(file, c->name);
1539 fprintf(file, "\n");
1541 /* iterate over all class entries */
1542 for (clsen = c->classes; clsen; clsen = clsen->next) {
1543 if (clsen->classobj) {
1544 log_println(" loaded %p", (void *) clsen->classobj);
1547 log_println(" unresolved");
1551 log_print(" loaders: ");
1552 for (lden = clsen->loaders; lden; lden = lden->next) {
1553 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1558 log_print(" constraints: ");
1559 for (lden = clsen->constraints; lden; lden = lden->next) {
1560 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
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: