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 8295 2007-08-11 17:57:24Z michi $
36 #include "mm/memory.h"
38 #include "threads/lock-common.h"
40 #include "toolbox/hashtable.h"
41 #include "toolbox/logging.h"
43 #include "vm/exceptions.h"
45 #include "vmcore/classcache.h"
46 #include "vmcore/utf8.h"
49 /*************************************************************************
53 The classcache has two functions:
55 1) caching the resolution of class references
56 2) storing and checking loading constraints
58 We will use the following terms in this description:
60 N a class name: a utf string
61 (N,L) a class reference with initiating loader L and class name N
62 C a class (object): the result of resolving a reference (N,L)
63 We will write resultion as
65 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
66 resolve to the same class C. So (N,L1,L2) means
69 The functions of the classcache require:
71 1) a mapping (N,L) |--> C for looking up prior resolution results.
72 2) storing the current set of loading constraints { (N,L1,L2) }
74 These functions can be rearranged like that:
76 a mapping N |--> (a mapping L |--> C or NULL,
77 a set of constraints {(L1,L2)})
79 Thus we can treat the mapping and constraints for each name N
80 separately. The implementation does this by keeping a hash table
81 mapping a name N to a `classcache_name_entry` which contains all
82 info with respect to N.
84 For a class name N we can define an equivalence relation ~N~ on
87 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
89 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
91 Also, if two references (N,L1) and (N,L2) resolve to the same class C
92 we have L1 ~N~ L2 because class loaders are required to return
93 consistent resolutions for a name N [XXX].
95 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
97 Cx...is a class C or NULL
98 IL...is the set of initiating loaders
99 CL...is the set of constrained loaders
101 Such a tuple is called `classcache_class_entry` in the source code.
103 The following holds for each tuple (Cx,IL,CL):
105 . (Cx is NULL) implies IL = {}.
107 . If Cx is a class, IL is the set of loaders that have been
108 recorded as initiating loaders for Cx. IL may be the
109 empty set {} in case Cx has already been defined but no
110 initiating loader has been recorded, yet.
112 . (IL u CL) is a subset of an equivalence class of ~N~.
114 (This means that all loaders in IL and CL must resolve
115 the name N to the same class.)
117 The following holds for the set of tuples { (Cx,IL,CL) }:
119 . For a given class C there is at most one tuple with Cx = C
120 in the set. (There may be an arbitrary number of tuples
121 with Cx = NULL, however.)
123 . For a given loader L there is at most one tuple with
126 The implementation stores sets of loaders as linked lists of
127 `classcache_loader_entry`s.
129 Comments about manipulating the classcache can be found in the
130 individual functions below.
132 *************************************************************************/
135 /* initial number of slots in the classcache hash table */
136 #define CLASSCACHE_INIT_SIZE 2048
138 /*============================================================================*/
140 /*============================================================================*/
142 /* #define CLASSCACHE_VERBOSE */
144 /*============================================================================*/
146 /*============================================================================*/
148 /*#define CLASSCACHE_STATS*/
150 #ifdef CLASSCACHE_STATS
151 static int stat_classnames_stored = 0;
152 static int stat_classes_stored = 0;
153 static int stat_trivial_constraints = 0;
154 static int stat_nontriv_constraints = 0;
155 static int stat_nontriv_constraints_both = 0;
156 static int stat_nontriv_constraints_merged = 0;
157 static int stat_nontriv_constraints_one = 0;
158 static int stat_nontriv_constraints_none = 0;
159 static int stat_new_loader_entry = 0;
160 static int stat_merge_class_entries = 0;
161 static int stat_merge_loader_entries = 0;
162 static int stat_lookup = 0;
163 static int stat_lookup_class_entry_checked = 0;
164 static int stat_lookup_loader_checked = 0;
165 static int stat_lookup_name = 0;
166 static int stat_lookup_name_entry = 0;
167 static int stat_lookup_name_notfound = 0;
168 static int stat_lookup_new_name = 0;
169 static int stat_lookup_new_name_entry = 0;
170 static int stat_lookup_new_name_collisions = 0;
171 static int stat_rehash_names = 0;
172 static int stat_rehash_names_collisions = 0;
174 #define CLASSCACHE_COUNT(cnt) (cnt)++
175 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
177 void classcache_print_statistics(FILE *file) {
178 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
179 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
180 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
181 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
182 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
183 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
184 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
185 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
186 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
187 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
188 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
189 fprintf(file,"lookups : %8d\n",stat_lookup);
190 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
191 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
192 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
193 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
194 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
195 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
196 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
197 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
198 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
199 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
202 #define CLASSCACHE_COUNT(cnt)
203 #define CLASSCACHE_COUNTIF(cond,cnt)
206 /*============================================================================*/
207 /* THREAD-SAFE LOCKING */
208 /*============================================================================*/
210 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
211 /* CAUTION: The static functions below are */
212 /* NOT synchronized! */
213 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
215 #if defined(ENABLE_THREADS)
216 # define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
217 # define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
219 # define CLASSCACHE_LOCK()
220 # define CLASSCACHE_UNLOCK()
223 /*============================================================================*/
224 /* GLOBAL VARIABLES */
225 /*============================================================================*/
227 hashtable hashtable_classcache;
229 #if defined(ENABLE_THREADS)
230 static java_object_t *lock_hashtable_classcache;
234 /*============================================================================*/
236 /*============================================================================*/
240 static void classcache_free_class_entry(classcache_class_entry *clsen);
241 static void classcache_remove_class_entry(classcache_name_entry *en,
242 classcache_class_entry *clsen);
244 /* hash function to use */
246 #define CLASSCACHE_HASH utf_full_hashkey
248 /* classcache_init *************************************************************
250 Initialize the class cache
252 Note: NOT synchronized!
254 *******************************************************************************/
256 bool classcache_init(void)
258 /* create the hashtable */
260 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
262 #if defined(ENABLE_THREADS)
263 /* create utf hashtable lock object */
265 lock_hashtable_classcache = NEW(java_object_t);
267 LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
270 /* everything's ok */
275 /* classcache_new_loader_entry *************************************************
277 Create a new classcache_loader_entry struct
278 (internally used helper function)
281 loader...........the ClassLoader object
282 next.............the next classcache_loader_entry
285 the new classcache_loader_entry
287 *******************************************************************************/
289 static classcache_loader_entry * classcache_new_loader_entry(
290 classloader * loader,
291 classcache_loader_entry * next)
293 classcache_loader_entry *lden;
295 lden = NEW(classcache_loader_entry);
296 lden->loader = loader;
298 CLASSCACHE_COUNT(stat_new_loader_entry);
303 /* classcache_merge_loaders ****************************************************
305 Merge two lists of loaders into one
306 (internally used helper function)
309 lista............first list (may be NULL)
310 listb............second list (may be NULL)
313 the merged list (may be NULL)
316 The lists given as arguments are destroyed!
318 *******************************************************************************/
320 static classcache_loader_entry * classcache_merge_loaders(
321 classcache_loader_entry * lista,
322 classcache_loader_entry * listb)
324 classcache_loader_entry *result;
325 classcache_loader_entry *ldenA;
326 classcache_loader_entry *ldenB;
327 classcache_loader_entry **chain;
329 CLASSCACHE_COUNT(stat_merge_loader_entries);
331 /* XXX This is a quadratic algorithm. If this ever
332 * becomes a problem, the loader lists should be
333 * stored as sorted lists and merged in linear time. */
338 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
340 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
341 if (ldenB->loader == ldenA->loader)
345 /* this loader is only in lista */
347 chain = &(ldenA->next);
350 /* XXX free the duplicated element */
354 /* concat listb to the result */
360 /* classcache_merge_class_entries **********************************************
362 Merge two `classcache_class_entry`s into one.
363 (internally used helper function)
366 en...............the classcache_name_entry containing both class entries
367 clsenA...........first class entry, will receive the result
368 clsenB...........second class entry
371 Either both entries must have the same classobj, or one of them has
375 clsenB is freed by this function!
377 *******************************************************************************/
379 static void classcache_merge_class_entries(classcache_name_entry *en,
380 classcache_class_entry *clsenA,
381 classcache_class_entry *clsenB)
383 #ifdef CLASSCACHE_VERBOSE
384 char logbuffer[1024];
390 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
392 #ifdef CLASSCACHE_VERBOSE
393 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
394 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
395 if (clsenA->classobj)
396 utf_cat_classname(logbuffer, clsenA->classobj->name);
397 if (clsenB->classobj)
398 utf_cat_classname(logbuffer, clsenB->classobj->name);
399 log_println(logbuffer);
402 CLASSCACHE_COUNT(stat_merge_class_entries);
404 /* clsenB will be merged into clsenA */
405 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
406 clsenB->loaders = NULL; /* these have been freed or reused */
408 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
409 clsenB->constraints);
410 clsenB->constraints = NULL; /* these have been freed or reused */
412 if (!clsenA->classobj)
413 clsenA->classobj = clsenB->classobj;
415 /* remove clsenB from the list of class entries */
416 classcache_remove_class_entry(en, clsenB);
420 /* classcache_lookup_name ******************************************************
422 Lookup a name in the first level of the cache
423 (internally used helper function)
426 name.............the name to look up
429 a pointer to the classcache_name_entry for this name, or
430 null if no entry was found.
432 *******************************************************************************/
434 static classcache_name_entry *classcache_lookup_name(utf *name)
436 classcache_name_entry *c; /* hash table element */
437 u4 key; /* hashkey computed from classname */
438 u4 slot; /* slot in hashtable */
440 CLASSCACHE_COUNT(stat_lookup_name);
442 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
443 slot = key & (hashtable_classcache.size - 1);
444 c = hashtable_classcache.ptr[slot];
446 /* search external hash chain for the entry */
449 /* entry found in hashtable */
450 CLASSCACHE_COUNT(stat_lookup_name_entry);
455 c = c->hashlink; /* next element in external chain */
460 CLASSCACHE_COUNT(stat_lookup_name_notfound);
465 /* classcache_new_name *********************************************************
467 Return a classcache_name_entry for the given name. The entry is created
468 if it is not already in the cache.
469 (internally used helper function)
472 name.............the name to look up / create an entry for
475 a pointer to the classcache_name_entry for this name
477 *******************************************************************************/
479 static classcache_name_entry *classcache_new_name(utf *name)
481 classcache_name_entry *c; /* hash table element */
482 u4 key; /* hashkey computed from classname */
483 u4 slot; /* slot in hashtable */
486 CLASSCACHE_COUNT(stat_lookup_new_name);
488 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
489 slot = key & (hashtable_classcache.size - 1);
490 c = hashtable_classcache.ptr[slot];
492 /* search external hash chain for the entry */
495 /* entry found in hashtable */
496 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
501 c = c->hashlink; /* next element in external chain */
504 /* location in hashtable found, create new entry */
506 c = NEW(classcache_name_entry);
511 /* insert entry into hashtable */
512 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
513 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
514 hashtable_classcache.ptr[slot] = c;
516 /* update number of hashtable-entries */
517 hashtable_classcache.entries++;
518 CLASSCACHE_COUNT(stat_classnames_stored);
520 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
521 /* reorganization of hashtable */
523 classcache_name_entry *c2;
524 hashtable newhash; /* the new hashtable */
526 CLASSCACHE_COUNT(stat_rehash_names);
528 /* create new hashtable, double the size */
530 hashtable_create(&newhash, hashtable_classcache.size * 2);
531 newhash.entries = hashtable_classcache.entries;
533 /* transfer elements to new hashtable */
535 for (i = 0; i < hashtable_classcache.size; i++) {
536 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
538 classcache_name_entry *nextc = c2->hashlink;
540 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
542 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
543 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
544 newhash.ptr[newslot] = c2;
550 /* dispose old table */
552 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
553 hashtable_classcache = newhash;
560 /* classcache_lookup ***********************************************************
562 Lookup a possibly loaded class
565 initloader.......initiating loader for resolving the class name
566 classname........class name to look up
569 The return value is a pointer to the cached class object,
570 or NULL, if the class is not in the cache.
572 Note: synchronized with global tablelock
574 *******************************************************************************/
576 classinfo *classcache_lookup(classloader *initloader, utf *classname)
578 classcache_name_entry *en;
579 classcache_class_entry *clsen;
580 classcache_loader_entry *lden;
581 classinfo *cls = NULL;
585 CLASSCACHE_COUNT(stat_lookup);
586 en = classcache_lookup_name(classname);
589 /* iterate over all class entries */
591 for (clsen = en->classes; clsen; clsen = clsen->next) {
592 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
593 /* check if this entry has been loaded by initloader */
595 for (lden = clsen->loaders; lden; lden = lden->next) {
596 CLASSCACHE_COUNT(stat_lookup_loader_checked);
597 if (lden->loader == initloader) {
598 /* found the loaded class entry */
600 assert(clsen->classobj);
601 cls = clsen->classobj;
614 /* classcache_lookup_defined ***************************************************
616 Lookup a class with the given name and defining loader
619 defloader........defining loader
620 classname........class name
623 The return value is a pointer to the cached class object,
624 or NULL, if the class is not in the cache.
626 *******************************************************************************/
628 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
630 classcache_name_entry *en;
631 classcache_class_entry *clsen;
632 classinfo *cls = NULL;
636 en = classcache_lookup_name(classname);
639 /* iterate over all class entries */
640 for (clsen = en->classes; clsen; clsen = clsen->next) {
641 if (!clsen->classobj)
644 /* check if this entry has been defined by defloader */
645 if (clsen->classobj->classloader == defloader) {
646 cls = clsen->classobj;
658 /* classcache_lookup_defined_or_initiated **************************************
660 Lookup a class that has been defined or initiated by the given loader
663 loader...........defining or initiating loader
664 classname........class name to look up
667 The return value is a pointer to the cached class object,
668 or NULL, if the class is not in the cache.
670 Note: synchronized with global tablelock
672 *******************************************************************************/
674 classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
677 classcache_name_entry *en;
678 classcache_class_entry *clsen;
679 classcache_loader_entry *lden;
680 classinfo *cls = NULL;
684 en = classcache_lookup_name(classname);
687 /* iterate over all class entries */
689 for (clsen = en->classes; clsen; clsen = clsen->next) {
691 /* check if this entry has been defined by loader */
692 if (clsen->classobj && clsen->classobj->classloader == loader) {
693 cls = clsen->classobj;
697 /* check if this entry has been initiated by loader */
698 for (lden = clsen->loaders; lden; lden = lden->next) {
699 if (lden->loader == loader) {
700 /* found the loaded class entry */
702 assert(clsen->classobj);
703 cls = clsen->classobj;
716 /* classcache_store ************************************************************
718 Store a loaded class. If a class of the same name has already been stored
719 with the same initiating loader, then the given class CLS is freed (if
720 possible) and the previously stored class is returned.
723 initloader.......initiating loader used to load the class
724 (may be NULL indicating the bootstrap loader)
725 cls..............class object to cache
726 mayfree..........true if CLS may be freed in case another class is
730 cls..............everything ok, the class was stored in the cache,
731 other classinfo..another class with the same (initloader,name) has been
732 stored earlier. CLS has been freed[1] and the earlier
733 stored class is returned.
734 NULL.............an exception has been thrown.
736 Note: synchronized with global tablelock
738 [1]...in case MAYFREE is true
740 *******************************************************************************/
742 classinfo *classcache_store(classloader *initloader, classinfo *cls,
745 classcache_name_entry *en;
746 classcache_class_entry *clsen;
747 classcache_class_entry *clsenB;
748 classcache_loader_entry *lden;
749 #ifdef CLASSCACHE_VERBOSE
750 char logbuffer[1024];
754 assert(cls->state & CLASS_LOADED);
758 #ifdef CLASSCACHE_VERBOSE
759 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
760 utf_cat_classname(logbuffer, cls->name);
761 strcat(logbuffer,")");
762 log_println(logbuffer);
765 en = classcache_new_name(cls->name);
769 /* iterate over all class entries */
770 for (clsen = en->classes; clsen; clsen = clsen->next) {
772 /* check if this entry has already been loaded by initloader */
773 for (lden = clsen->loaders; lden; lden = lden->next) {
774 if (lden->loader == initloader) {
775 if (clsen->classobj != cls) {
776 /* A class with the same (initloader,name) pair has been stored already. */
777 /* We free the given class and return the earlier one. */
778 #ifdef CLASSCACHE_VERBOSE
779 log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
781 assert(clsen->classobj);
784 cls = clsen->classobj;
790 /* {This entry has not been resolved with initloader} */
792 /* check if initloader is constrained to this entry */
793 for (lden = clsen->constraints; lden; lden = lden->next) {
794 if (lden->loader == initloader) {
795 /* we have to use this entry. check if it has been resolved */
796 if (clsen->classobj) {
797 /* check if is has already been resolved to another class */
798 if (clsen->classobj != cls) {
799 /* a loading constraint is violated */
800 exceptions_throw_linkageerror("loading constraint violated: ", cls);
801 goto return_exception;
804 /* record initloader as initiating loader */
805 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
809 /* {this is the first resolution for this entry} */
810 /* record initloader as initiating loader */
811 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
813 /* maybe we can merge this entry with another one */
814 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
815 /* we dont want the entry that we have already */
816 if (clsenB->classobj == cls) {
817 /* this entry has the same classobj. let's merge them */
818 classcache_merge_class_entries(en,clsen,clsenB);
823 /* record the loaded class object */
824 clsen->classobj = cls;
825 CLASSCACHE_COUNT(stat_classes_stored);
834 /* {There is no class entry containing initloader as initiating
835 * or constrained loader.} */
837 /* we look for a class entry with the same classobj we want to store */
838 for (clsen = en->classes; clsen; clsen = clsen->next) {
839 if (clsen->classobj == cls) {
840 /* this entry is about the same classobj. let's use it */
841 /* check if this entry has already been loaded by initloader */
842 for (lden = clsen->loaders; lden; lden = lden->next) {
843 if (lden->loader == initloader)
846 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
851 /* create a new class entry for this class object with */
852 /* initiating loader initloader */
854 clsen = NEW(classcache_class_entry);
855 clsen->classobj = cls;
856 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
857 clsen->constraints = NULL;
859 clsen->next = en->classes;
861 CLASSCACHE_COUNT(stat_classes_stored);
864 #ifdef CLASSCACHE_VERBOSE
865 classcache_debug_dump(stdout,cls->name);
872 return NULL; /* exception */
875 /* classcache_store_unique *****************************************************
877 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
878 aroung classcache_store that throws an exception if a class with the same
879 name has already been loaded by the bootstrap loader.
881 This function is used to register a few special classes during startup.
882 It should not be used otherwise.
885 cls..............class object to cache
888 true.............everything ok, the class was stored.
889 false............an exception has been thrown.
891 Note: synchronized with global tablelock
893 *******************************************************************************/
895 bool classcache_store_unique(classinfo *cls)
899 result = classcache_store(NULL,cls,false);
904 exceptions_throw_internalerror("class already stored in the class cache");
911 /* classcache_store_defined ****************************************************
913 Store a loaded class after it has been defined. If the class has already
914 been defined by the same defining loader in another thread, free the given
915 class and returned the one which has been defined earlier.
918 cls..............class object to store. classloader must be set
919 (classloader may be NULL, for bootloader)
922 cls..............everything ok, the class was stored the cache,
923 other classinfo..the class had already been defined, CLS was freed, the
924 class which was defined earlier is returned,
925 NULL.............an exception has been thrown.
927 *******************************************************************************/
929 classinfo *classcache_store_defined(classinfo *cls)
931 classcache_name_entry *en;
932 classcache_class_entry *clsen;
933 #ifdef CLASSCACHE_VERBOSE
934 char logbuffer[1024];
938 assert(cls->state & CLASS_LOADED);
942 #ifdef CLASSCACHE_VERBOSE
943 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
944 utf_cat_classname(logbuffer, cls->name);
945 strcat(logbuffer,")");
946 log_println(logbuffer);
949 en = classcache_new_name(cls->name);
953 /* iterate over all class entries */
954 for (clsen = en->classes; clsen; clsen = clsen->next) {
956 /* check if this class has been defined by the same classloader */
957 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
958 /* we found an earlier definition, delete the newer one */
959 /* (if it is a different classinfo) */
960 if (clsen->classobj != cls) {
961 #ifdef CLASSCACHE_VERBOSE
962 log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
965 cls = clsen->classobj;
971 /* create a new class entry for this class object */
972 /* the list of initiating loaders is empty at this point */
974 clsen = NEW(classcache_class_entry);
975 clsen->classobj = cls;
976 clsen->loaders = NULL;
977 clsen->constraints = NULL;
979 clsen->next = en->classes;
981 CLASSCACHE_COUNT(stat_classes_stored);
984 #ifdef CLASSCACHE_VERBOSE
985 classcache_debug_dump(stdout,cls->name);
991 /* classcache_find_loader ******************************************************
993 Find the class entry loaded by or constrained to a given loader
994 (internally used helper function)
997 entry............the classcache_name_entry
998 loader...........the loader to look for
1001 the classcache_class_entry for the given loader, or
1002 NULL if no entry was found
1004 *******************************************************************************/
1006 static classcache_class_entry * classcache_find_loader(
1007 classcache_name_entry * entry,
1008 classloader * loader)
1010 classcache_class_entry *clsen;
1011 classcache_loader_entry *lden;
1015 /* iterate over all class entries */
1016 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1018 /* check if this entry has already been loaded by initloader */
1019 for (lden = clsen->loaders; lden; lden = lden->next) {
1020 if (lden->loader == loader)
1021 return clsen; /* found */
1024 /* check if loader is constrained to this entry */
1025 for (lden = clsen->constraints; lden; lden = lden->next) {
1026 if (lden->loader == loader)
1027 return clsen; /* found */
1035 /* classcache_free_class_entry *************************************************
1037 Free the memory used by a class entry
1040 clsen............the classcache_class_entry to free
1042 *******************************************************************************/
1044 static void classcache_free_class_entry(classcache_class_entry * clsen)
1046 classcache_loader_entry *lden;
1047 classcache_loader_entry *next;
1051 for (lden = clsen->loaders; lden; lden = next) {
1053 FREE(lden, classcache_loader_entry);
1055 for (lden = clsen->constraints; lden; lden = next) {
1057 FREE(lden, classcache_loader_entry);
1060 FREE(clsen, classcache_class_entry);
1063 /* classcache_remove_class_entry ***********************************************
1065 Remove a classcache_class_entry from the list of possible resolution of
1067 (internally used helper function)
1070 entry............the classcache_name_entry
1071 clsen............the classcache_class_entry to remove
1073 *******************************************************************************/
1075 static void classcache_remove_class_entry(classcache_name_entry * entry,
1076 classcache_class_entry * clsen)
1078 classcache_class_entry **chain;
1083 chain = &(entry->classes);
1085 if (*chain == clsen) {
1086 *chain = clsen->next;
1087 classcache_free_class_entry(clsen);
1090 chain = &((*chain)->next);
1094 /* classcache_free_name_entry **************************************************
1096 Free the memory used by a name entry
1099 entry............the classcache_name_entry to free
1101 *******************************************************************************/
1103 static void classcache_free_name_entry(classcache_name_entry * entry)
1105 classcache_class_entry *clsen;
1106 classcache_class_entry *next;
1110 for (clsen = entry->classes; clsen; clsen = next) {
1112 classcache_free_class_entry(clsen);
1115 FREE(entry, classcache_name_entry);
1118 /* classcache_free *************************************************************
1120 Free the memory used by the class cache
1123 The class cache may not be used any more after this call, except
1124 when it is reinitialized with classcache_init.
1126 Note: NOT synchronized!
1128 *******************************************************************************/
1130 void classcache_free(void)
1133 classcache_name_entry *entry;
1134 classcache_name_entry *next;
1136 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1137 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1138 next = entry->hashlink;
1139 classcache_free_name_entry(entry);
1143 MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1144 hashtable_classcache.size = 0;
1145 hashtable_classcache.entries = 0;
1146 hashtable_classcache.ptr = NULL;
1149 /* classcache_add_constraint ***************************************************
1151 Add a loading constraint
1154 a................first initiating loader
1155 b................second initiating loader
1156 classname........class name
1159 true.............everything ok, the constraint has been added,
1160 false............an exception has been thrown.
1162 Note: synchronized with global tablelock
1164 *******************************************************************************/
1166 #if defined(ENABLE_VERIFIER)
1167 bool classcache_add_constraint(classloader * a,
1171 classcache_name_entry *en;
1172 classcache_class_entry *clsenA;
1173 classcache_class_entry *clsenB;
1177 #ifdef CLASSCACHE_VERBOSE
1179 log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1180 utf_fprint_printable_ascii_classname(stdout, classname);
1185 /* a constraint with a == b is trivially satisfied */
1187 CLASSCACHE_COUNT(stat_trivial_constraints);
1193 en = classcache_new_name(classname);
1196 CLASSCACHE_COUNT(stat_nontriv_constraints);
1198 /* find the entry loaded by / constrained to each loader */
1199 clsenA = classcache_find_loader(en, a);
1200 clsenB = classcache_find_loader(en, b);
1202 if (clsenA && clsenB) {
1203 /* { both loaders have corresponding entries } */
1204 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1206 /* if the entries are the same, the constraint is already recorded */
1207 if (clsenA == clsenB)
1208 goto return_success;
1210 /* check if the entries can be merged */
1211 if (clsenA->classobj && clsenB->classobj
1212 && clsenA->classobj != clsenB->classobj) {
1213 /* no, the constraint is violated */
1214 exceptions_throw_linkageerror("loading constraint violated: ",
1216 goto return_exception;
1219 /* yes, merge the entries */
1220 classcache_merge_class_entries(en,clsenA,clsenB);
1221 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1224 /* { at most one of the loaders has a corresponding entry } */
1226 /* set clsenA to the single class entry we have */
1231 /* { no loader has a corresponding entry } */
1232 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1234 /* create a new class entry with the constraint (a,b,en->name) */
1235 clsenA = NEW(classcache_class_entry);
1236 clsenA->classobj = NULL;
1237 clsenA->loaders = NULL;
1238 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1239 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1241 clsenA->next = en->classes;
1242 en->classes = clsenA;
1245 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1247 /* make b the loader that has no corresponding entry */
1251 /* loader b must be added to entry clsenA */
1252 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1257 CLASSCACHE_UNLOCK();
1261 CLASSCACHE_UNLOCK();
1262 return false; /* exception */
1264 #endif /* defined(ENABLE_VERIFIER) */
1266 /* classcache_add_constraints_for_params ***************************************
1268 Add loading constraints for the parameters and return type of
1272 a................first initiating loader
1273 b................second initiating loader
1274 m................methodinfo
1277 true.............everything ok, the constraints have been added,
1278 false............an exception has been thrown.
1280 Note: synchronized with global tablelock
1282 *******************************************************************************/
1284 #if defined(ENABLE_VERIFIER)
1285 bool classcache_add_constraints_for_params(classloader * a,
1293 /* a constraint with a == b is trivially satisfied */
1299 /* get the parsed descriptor */
1305 /* constrain the return type */
1307 if (md->returntype.type == TYPE_ADR) {
1308 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1309 return false; /* exception */
1312 /* constrain each reference type used in the parameters */
1314 td = md->paramtypes;
1317 if (td->type != TYPE_ADR)
1320 if (!classcache_add_constraint(a, b, td->classref->name))
1321 return false; /* exception */
1327 #endif /* defined(ENABLE_VERIFIER) */
1330 /* classcache_number_of_loaded_classes *****************************************
1332 Counts the number of loaded classes and returns it.
1334 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1337 *******************************************************************************/
1339 static s4 classcache_number_of_loaded_classes(void)
1341 classcache_name_entry *en;
1342 classcache_class_entry *clsen;
1346 /* initialize class counter */
1350 for (i = 0; i < hashtable_classcache.size; i++) {
1351 /* iterate over hashlink */
1353 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1354 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1356 if (en->name->text[0] == '$')
1359 /* iterate over classes with same name */
1361 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1362 /* get only loaded classes */
1364 if (clsen->classobj != NULL)
1374 /* classcache_get_loaded_class_count *******************************************
1376 Counts the number of loaded classes and returns it.
1378 *******************************************************************************/
1380 s4 classcache_get_loaded_class_count(void)
1386 count = classcache_number_of_loaded_classes();
1388 CLASSCACHE_UNLOCK();
1394 /* classcache_get_loaded_classes ***********************************************
1396 Returns an array of all loaded classes as array. The array is
1397 allocaed on the Java heap.
1399 *******************************************************************************/
1401 #if defined(ENABLE_JVMTI)
1402 void classcache_get_loaded_classes(s4 *class_count_ptr,
1403 classinfo ***classes_ptr)
1405 classinfo **classes;
1407 classcache_name_entry *en;
1408 classcache_class_entry *clsen;
1414 /* get the number of loaded classes and allocate the array */
1416 class_count = classcache_number_of_loaded_classes();
1418 classes = GCMNEW(classinfo*, class_count);
1420 /* look in every slot of the hashtable */
1422 for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1423 /* iterate over hashlink */
1425 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1426 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1428 if (en->name->text[0] == '$')
1431 /* iterate over classes with same name */
1433 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1434 /* get only loaded classes */
1436 if (clsen->classobj != NULL) {
1437 classes[j] = clsen->classobj;
1444 /* pass the return values */
1446 *class_count_ptr = class_count;
1447 *classes_ptr = classes;
1449 CLASSCACHE_UNLOCK();
1451 #endif /* defined(ENABLE_JVMTI) */
1454 /* classcache_foreach_loaded_class *********************************************
1456 Calls the given function for each loaded class.
1458 *******************************************************************************/
1460 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1463 classcache_name_entry *en;
1464 classcache_class_entry *clsen;
1469 /* look in every slot of the hashtable */
1471 for (i = 0; i < hashtable_classcache.size; i++) {
1472 /* iterate over hashlink */
1474 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1475 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1477 if (en->name->text[0] == '$')
1480 /* iterate over classes with same name */
1482 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1483 /* get only loaded classes */
1485 if (clsen->classobj != NULL) {
1486 (*func)(clsen->classobj, data);
1492 CLASSCACHE_UNLOCK();
1496 /*============================================================================*/
1498 /*============================================================================*/
1500 /* classcache_debug_dump *******************************************************
1502 Print the contents of the loaded class cache to a stream
1505 file.............output stream
1506 only.............if != NULL, only print entries for this name
1507 (Currently we print also the rest of the hash chain to
1508 get a feel for the average length of hash chains.)
1510 Note: synchronized with global tablelock
1512 *******************************************************************************/
1515 void classcache_debug_dump(FILE * file,utf *only)
1517 classcache_name_entry *c;
1518 classcache_class_entry *clsen;
1519 classcache_loader_entry *lden;
1524 log_println("=== [loaded class cache] =====================================");
1525 log_println("hash size : %d", (int) hashtable_classcache.size);
1526 log_println("hash entries: %d", (int) hashtable_classcache.entries);
1530 c = classcache_lookup_name(only);
1531 slot = 0; /* avoid compiler warning */
1535 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1536 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1539 for (; c; c = c->hashlink) {
1540 utf_fprint_printable_ascii_classname(file, c->name);
1541 fprintf(file, "\n");
1543 /* iterate over all class entries */
1544 for (clsen = c->classes; clsen; clsen = clsen->next) {
1545 if (clsen->classobj) {
1546 log_println(" loaded %p", (void *) clsen->classobj);
1549 log_println(" unresolved");
1553 log_print(" loaders: ");
1554 for (lden = clsen->loaders; lden; lden = lden->next) {
1555 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1560 log_print(" constraints: ");
1561 for (lden = clsen->constraints; lden; lden = lden->next) {
1562 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1571 fprintf(file, "\n==============================================================\n\n");
1573 CLASSCACHE_UNLOCK();
1578 * These are local overrides for various environment variables in Emacs.
1579 * Please do not remove this and leave it at the end of the file, where
1580 * Emacs will automagically detect them.
1581 * ---------------------------------------------------------------------
1584 * indent-tabs-mode: t
1588 * vim:noexpandtab:sw=4:ts=4: