1 /* src/vm/classcache.cpp - loaded class cache and loading constraints
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "mm/memory.hpp"
34 #include "threads/lock.hpp"
35 #include "threads/mutex.hpp"
37 #include "toolbox/hashtable.h"
38 #include "toolbox/logging.hpp"
40 #include "vm/classcache.hpp"
41 #include "vm/exceptions.hpp"
42 #include "vm/options.h"
46 /*************************************************************************
50 The classcache has two functions:
52 1) caching the resolution of class references
53 2) storing and checking loading constraints
55 We will use the following terms in this description:
57 N a class name: a utf string
58 (N,L) a class reference with initiating loader L and class name N
59 C a class (object): the result of resolving a reference (N,L)
60 We will write resultion as
62 (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
63 resolve to the same class C. So (N,L1,L2) means
66 The functions of the classcache require:
68 1) a mapping (N,L) |--> C for looking up prior resolution results.
69 2) storing the current set of loading constraints { (N,L1,L2) }
71 These functions can be rearranged like that:
73 a mapping N |--> (a mapping L |--> C or NULL,
74 a set of constraints {(L1,L2)})
76 Thus we can treat the mapping and constraints for each name N
77 separately. The implementation does this by keeping a hash table
78 mapping a name N to a `classcache_name_entry` which contains all
79 info with respect to N.
81 For a class name N we can define an equivalence relation ~N~ on
84 L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
86 A loading constraint (N,L1,L2) implies L1 ~N~ L2.
88 Also, if two references (N,L1) and (N,L2) resolve to the same class C
89 we have L1 ~N~ L2 because class loaders are required to return
90 consistent resolutions for a name N [XXX].
92 A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
94 Cx...is a class C or NULL
95 IL...is the set of initiating loaders
96 CL...is the set of constrained loaders
98 Such a tuple is called `classcache_class_entry` in the source code.
100 The following holds for each tuple (Cx,IL,CL):
102 . (Cx is NULL) implies IL = {}.
104 . If Cx is a class, IL is the set of loaders that have been
105 recorded as initiating loaders for Cx. IL may be the
106 empty set {} in case Cx has already been defined but no
107 initiating loader has been recorded, yet.
109 . (IL u CL) is a subset of an equivalence class of ~N~.
111 (This means that all loaders in IL and CL must resolve
112 the name N to the same class.)
114 The following holds for the set of tuples { (Cx,IL,CL) }:
116 . For a given class C there is at most one tuple with Cx = C
117 in the set. (There may be an arbitrary number of tuples
118 with Cx = NULL, however.)
120 . For a given loader L there is at most one tuple with
123 The implementation stores sets of loaders as linked lists of
124 `classcache_loader_entry`s.
126 Comments about manipulating the classcache can be found in the
127 individual functions below.
129 *************************************************************************/
132 /* initial number of slots in the classcache hash table */
133 #define CLASSCACHE_INIT_SIZE 2048
135 /*============================================================================*/
137 /*============================================================================*/
139 /* #define CLASSCACHE_VERBOSE */
141 /*============================================================================*/
143 /*============================================================================*/
145 /*#define CLASSCACHE_STATS*/
147 #ifdef CLASSCACHE_STATS
148 static int stat_classnames_stored = 0;
149 static int stat_classes_stored = 0;
150 static int stat_trivial_constraints = 0;
151 static int stat_nontriv_constraints = 0;
152 static int stat_nontriv_constraints_both = 0;
153 static int stat_nontriv_constraints_merged = 0;
154 static int stat_nontriv_constraints_one = 0;
155 static int stat_nontriv_constraints_none = 0;
156 static int stat_new_loader_entry = 0;
157 static int stat_merge_class_entries = 0;
158 static int stat_merge_loader_entries = 0;
159 static int stat_lookup = 0;
160 static int stat_lookup_class_entry_checked = 0;
161 static int stat_lookup_loader_checked = 0;
162 static int stat_lookup_name = 0;
163 static int stat_lookup_name_entry = 0;
164 static int stat_lookup_name_notfound = 0;
165 static int stat_lookup_new_name = 0;
166 static int stat_lookup_new_name_entry = 0;
167 static int stat_lookup_new_name_collisions = 0;
168 static int stat_rehash_names = 0;
169 static int stat_rehash_names_collisions = 0;
171 #define CLASSCACHE_COUNT(cnt) (cnt)++
172 #define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
174 void classcache_print_statistics(FILE *file) {
175 fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
176 fprintf(file,"classes stored : %8d\n",stat_classes_stored);
177 fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
178 fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
179 fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
180 fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
181 fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
182 fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
183 fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
184 fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
185 fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
186 fprintf(file,"lookups : %8d\n",stat_lookup);
187 fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
188 fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
189 fprintf(file,"lookup name : %8d\n",stat_lookup_name);
190 fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
191 fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
192 fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
193 fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
194 fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
195 fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
196 fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
199 #define CLASSCACHE_COUNT(cnt)
200 #define CLASSCACHE_COUNTIF(cond,cnt)
203 /*============================================================================*/
204 /* THREAD-SAFE LOCKING */
205 /*============================================================================*/
207 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
208 /* CAUTION: The static functions below are */
209 /* NOT synchronized! */
210 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
212 #if defined(ENABLE_THREADS)
213 # define CLASSCACHE_LOCK() classcache_hashtable_mutex->lock();
214 # define CLASSCACHE_UNLOCK() classcache_hashtable_mutex->unlock();
216 # define CLASSCACHE_LOCK()
217 # define CLASSCACHE_UNLOCK()
220 /*============================================================================*/
221 /* GLOBAL VARIABLES */
222 /*============================================================================*/
224 hashtable hashtable_classcache;
226 #if defined(ENABLE_THREADS)
227 static Mutex *classcache_hashtable_mutex;
231 /*============================================================================*/
233 /*============================================================================*/
237 static void classcache_free_class_entry(classcache_class_entry *clsen);
238 static void classcache_remove_class_entry(classcache_name_entry *en,
239 classcache_class_entry *clsen);
241 /* hash function to use */
243 #define CLASSCACHE_HASH utf_full_hashkey
245 /* classcache_init *************************************************************
247 Initialize the class cache
249 Note: NOT synchronized!
251 *******************************************************************************/
253 bool classcache_init(void)
255 TRACESUBSYSTEMINITIALIZATION("classcache_init");
257 /* create the hashtable */
259 hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
261 #if defined(ENABLE_THREADS)
262 /* create utf hashtable mutex */
264 classcache_hashtable_mutex = new Mutex();
267 /* everything's ok */
272 /* classcache_new_loader_entry *************************************************
274 Create a new classcache_loader_entry struct
275 (internally used helper function)
278 loader...........the ClassLoader object
279 next.............the next classcache_loader_entry
282 the new classcache_loader_entry
284 *******************************************************************************/
286 static classcache_loader_entry * classcache_new_loader_entry(
287 classloader_t * loader,
288 classcache_loader_entry * next)
290 classcache_loader_entry *lden;
292 lden = NEW(classcache_loader_entry);
293 lden->loader = loader;
295 CLASSCACHE_COUNT(stat_new_loader_entry);
300 /* classcache_merge_loaders ****************************************************
302 Merge two lists of loaders into one
303 (internally used helper function)
306 lista............first list (may be NULL)
307 listb............second list (may be NULL)
310 the merged list (may be NULL)
313 The lists given as arguments are destroyed!
315 *******************************************************************************/
317 static classcache_loader_entry * classcache_merge_loaders(
318 classcache_loader_entry * lista,
319 classcache_loader_entry * listb)
321 classcache_loader_entry *result;
322 classcache_loader_entry *ldenA;
323 classcache_loader_entry *ldenB;
324 classcache_loader_entry **chain;
326 CLASSCACHE_COUNT(stat_merge_loader_entries);
328 /* XXX This is a quadratic algorithm. If this ever
329 * becomes a problem, the loader lists should be
330 * stored as sorted lists and merged in linear time. */
335 for (ldenA = lista; ldenA; ldenA = ldenA->next) {
337 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
338 if (ldenB->loader == ldenA->loader)
342 /* this loader is only in lista */
344 chain = &(ldenA->next);
347 /* XXX free the duplicated element */
351 /* concat listb to the result */
357 /* classcache_merge_class_entries **********************************************
359 Merge two `classcache_class_entry`s into one.
360 (internally used helper function)
363 en...............the classcache_name_entry containing both class entries
364 clsenA...........first class entry, will receive the result
365 clsenB...........second class entry
368 Either both entries must have the same classobj, or one of them has
372 clsenB is freed by this function!
374 *******************************************************************************/
376 static void classcache_merge_class_entries(classcache_name_entry *en,
377 classcache_class_entry *clsenA,
378 classcache_class_entry *clsenB)
380 #ifdef CLASSCACHE_VERBOSE
381 char logbuffer[1024];
387 assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
389 #ifdef CLASSCACHE_VERBOSE
390 sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
391 (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
392 if (clsenA->classobj)
393 utf_cat_classname(logbuffer, clsenA->classobj->name);
394 if (clsenB->classobj)
395 utf_cat_classname(logbuffer, clsenB->classobj->name);
396 log_println(logbuffer);
399 CLASSCACHE_COUNT(stat_merge_class_entries);
401 /* clsenB will be merged into clsenA */
402 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
403 clsenB->loaders = NULL; /* these have been freed or reused */
405 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
406 clsenB->constraints);
407 clsenB->constraints = NULL; /* these have been freed or reused */
409 if (!clsenA->classobj)
410 clsenA->classobj = clsenB->classobj;
412 /* remove clsenB from the list of class entries */
413 classcache_remove_class_entry(en, clsenB);
417 /* classcache_lookup_name ******************************************************
419 Lookup a name in the first level of the cache
420 (internally used helper function)
423 name.............the name to look up
426 a pointer to the classcache_name_entry for this name, or
427 null if no entry was found.
429 *******************************************************************************/
431 static classcache_name_entry *classcache_lookup_name(utf *name)
433 classcache_name_entry *c; /* hash table element */
434 u4 key; /* hashkey computed from classname */
435 u4 slot; /* slot in hashtable */
437 CLASSCACHE_COUNT(stat_lookup_name);
439 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
440 slot = key & (hashtable_classcache.size - 1);
441 c = (classcache_name_entry*) hashtable_classcache.ptr[slot];
443 /* search external hash chain for the entry */
446 /* entry found in hashtable */
447 CLASSCACHE_COUNT(stat_lookup_name_entry);
452 c = c->hashlink; /* next element in external chain */
457 CLASSCACHE_COUNT(stat_lookup_name_notfound);
462 /* classcache_new_name *********************************************************
464 Return a classcache_name_entry for the given name. The entry is created
465 if it is not already in the cache.
466 (internally used helper function)
469 name.............the name to look up / create an entry for
472 a pointer to the classcache_name_entry for this name
474 *******************************************************************************/
476 static classcache_name_entry *classcache_new_name(utf *name)
478 classcache_name_entry *c; /* hash table element */
479 u4 key; /* hashkey computed from classname */
480 u4 slot; /* slot in hashtable */
483 CLASSCACHE_COUNT(stat_lookup_new_name);
485 key = CLASSCACHE_HASH(name->text, (u4) name->blength);
486 slot = key & (hashtable_classcache.size - 1);
487 c = (classcache_name_entry*) hashtable_classcache.ptr[slot];
489 /* search external hash chain for the entry */
492 /* entry found in hashtable */
493 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
498 c = c->hashlink; /* next element in external chain */
501 /* location in hashtable found, create new entry */
503 c = NEW(classcache_name_entry);
508 /* insert entry into hashtable */
509 c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
510 CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
511 hashtable_classcache.ptr[slot] = c;
513 /* update number of hashtable-entries */
514 hashtable_classcache.entries++;
515 CLASSCACHE_COUNT(stat_classnames_stored);
517 if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
518 /* reorganization of hashtable */
520 classcache_name_entry *c2;
521 hashtable newhash; /* the new hashtable */
523 CLASSCACHE_COUNT(stat_rehash_names);
525 /* create new hashtable, double the size */
527 hashtable_create(&newhash, hashtable_classcache.size * 2);
528 newhash.entries = hashtable_classcache.entries;
530 /* transfer elements to new hashtable */
532 for (i = 0; i < hashtable_classcache.size; i++) {
533 c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
535 classcache_name_entry *nextc = c2->hashlink;
537 (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
539 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
540 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
541 newhash.ptr[newslot] = c2;
547 /* dispose old table */
549 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
550 hashtable_classcache = newhash;
557 /* classcache_lookup ***********************************************************
559 Lookup a possibly loaded class
562 initloader.......initiating loader for resolving the class name
563 classname........class name to look up
566 The return value is a pointer to the cached class object,
567 or NULL, if the class is not in the cache.
569 Note: synchronized with global tablelock
571 *******************************************************************************/
573 classinfo *classcache_lookup(classloader_t *initloader, utf *classname)
575 classcache_name_entry *en;
576 classcache_class_entry *clsen;
577 classcache_loader_entry *lden;
578 classinfo *cls = NULL;
582 CLASSCACHE_COUNT(stat_lookup);
583 en = classcache_lookup_name(classname);
586 /* iterate over all class entries */
588 for (clsen = en->classes; clsen; clsen = clsen->next) {
589 CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
590 /* check if this entry has been loaded by initloader */
592 for (lden = clsen->loaders; lden; lden = lden->next) {
593 CLASSCACHE_COUNT(stat_lookup_loader_checked);
594 if (lden->loader == initloader) {
595 /* found the loaded class entry */
597 assert(clsen->classobj);
598 cls = clsen->classobj;
611 /* classcache_lookup_defined ***************************************************
613 Lookup a class with the given name and defining loader
616 defloader........defining loader
617 classname........class name
620 The return value is a pointer to the cached class object,
621 or NULL, if the class is not in the cache.
623 *******************************************************************************/
625 classinfo *classcache_lookup_defined(classloader_t *defloader, utf *classname)
627 classcache_name_entry *en;
628 classcache_class_entry *clsen;
629 classinfo *cls = NULL;
633 en = classcache_lookup_name(classname);
636 /* iterate over all class entries */
637 for (clsen = en->classes; clsen; clsen = clsen->next) {
638 if (!clsen->classobj)
641 /* check if this entry has been defined by defloader */
642 if (clsen->classobj->classloader == defloader) {
643 cls = clsen->classobj;
655 /* classcache_lookup_defined_or_initiated **************************************
657 Lookup a class that has been defined or initiated by the given loader
660 loader...........defining or initiating loader
661 classname........class name to look up
664 The return value is a pointer to the cached class object,
665 or NULL, if the class is not in the cache.
667 Note: synchronized with global tablelock
669 *******************************************************************************/
671 classinfo *classcache_lookup_defined_or_initiated(classloader_t *loader,
674 classcache_name_entry *en;
675 classcache_class_entry *clsen;
676 classcache_loader_entry *lden;
677 classinfo *cls = NULL;
681 en = classcache_lookup_name(classname);
684 /* iterate over all class entries */
686 for (clsen = en->classes; clsen; clsen = clsen->next) {
688 /* check if this entry has been defined by loader */
689 if (clsen->classobj && clsen->classobj->classloader == loader) {
690 cls = clsen->classobj;
694 /* check if this entry has been initiated by loader */
695 for (lden = clsen->loaders; lden; lden = lden->next) {
696 if (lden->loader == loader) {
697 /* found the loaded class entry */
699 assert(clsen->classobj);
700 cls = clsen->classobj;
713 /* classcache_store ************************************************************
715 Store a loaded class. If a class of the same name has already been stored
716 with the same initiating loader, then the given class CLS is freed (if
717 possible) and the previously stored class is returned.
720 initloader.......initiating loader used to load the class
721 (may be NULL indicating the bootstrap loader)
722 cls..............class object to cache
723 mayfree..........true if CLS may be freed in case another class is
727 cls..............everything ok, the class was stored in the cache,
728 other classinfo..another class with the same (initloader,name) has been
729 stored earlier. CLS has been freed[1] and the earlier
730 stored class is returned.
731 NULL.............an exception has been thrown.
733 Note: synchronized with global tablelock
735 [1]...in case MAYFREE is true
737 *******************************************************************************/
739 classinfo *classcache_store(classloader_t *initloader, classinfo *cls,
742 classcache_name_entry *en;
743 classcache_class_entry *clsen;
744 classcache_class_entry *clsenB;
745 classcache_loader_entry *lden;
746 #ifdef CLASSCACHE_VERBOSE
747 char logbuffer[1024];
751 assert(cls->state & CLASS_LOADED);
755 #ifdef CLASSCACHE_VERBOSE
756 sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
757 utf_cat_classname(logbuffer, cls->name);
758 strcat(logbuffer,")");
759 log_println(logbuffer);
762 en = classcache_new_name(cls->name);
766 /* iterate over all class entries */
767 for (clsen = en->classes; clsen; clsen = clsen->next) {
769 /* check if this entry has already been loaded by initloader */
770 for (lden = clsen->loaders; lden; lden = lden->next) {
771 if (lden->loader == initloader) {
772 if (clsen->classobj != cls) {
773 /* A class with the same (initloader,name) pair has been stored already. */
774 /* We free the given class and return the earlier one. */
775 #ifdef CLASSCACHE_VERBOSE
776 log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
778 assert(clsen->classobj);
781 cls = clsen->classobj;
787 /* {This entry has not been resolved with initloader} */
789 /* check if initloader is constrained to this entry */
790 for (lden = clsen->constraints; lden; lden = lden->next) {
791 if (lden->loader == initloader) {
792 /* we have to use this entry. check if it has been resolved */
793 if (clsen->classobj) {
794 /* check if is has already been resolved to another class */
795 if (clsen->classobj != cls) {
796 /* a loading constraint is violated */
797 exceptions_throw_linkageerror("loading constraint violated: ", cls);
798 goto return_exception;
801 /* record initloader as initiating loader */
802 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
806 /* {this is the first resolution for this entry} */
807 /* record initloader as initiating loader */
808 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
810 /* maybe we can merge this entry with another one */
811 for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
812 /* we dont want the entry that we have already */
813 if (clsenB->classobj == cls) {
814 /* this entry has the same classobj. let's merge them */
815 classcache_merge_class_entries(en,clsen,clsenB);
820 /* record the loaded class object */
821 clsen->classobj = cls;
822 CLASSCACHE_COUNT(stat_classes_stored);
831 /* {There is no class entry containing initloader as initiating
832 * or constrained loader.} */
834 /* we look for a class entry with the same classobj we want to store */
835 for (clsen = en->classes; clsen; clsen = clsen->next) {
836 if (clsen->classobj == cls) {
837 /* this entry is about the same classobj. let's use it */
838 /* check if this entry has already been loaded by initloader */
839 for (lden = clsen->loaders; lden; lden = lden->next) {
840 if (lden->loader == initloader)
843 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
848 /* create a new class entry for this class object with */
849 /* initiating loader initloader */
851 clsen = NEW(classcache_class_entry);
852 clsen->classobj = cls;
853 clsen->loaders = classcache_new_loader_entry(initloader, NULL);
854 clsen->constraints = NULL;
856 clsen->next = en->classes;
858 CLASSCACHE_COUNT(stat_classes_stored);
861 #ifdef CLASSCACHE_VERBOSE
862 classcache_debug_dump(stdout,cls->name);
869 return NULL; /* exception */
872 /* classcache_store_unique *****************************************************
874 Store a loaded class as loaded by the bootstrap loader. This is a wrapper
875 aroung classcache_store that throws an exception if a class with the same
876 name has already been loaded by the bootstrap loader.
878 This function is used to register a few special classes during startup.
879 It should not be used otherwise.
882 cls..............class object to cache
885 true.............everything ok, the class was stored.
886 false............an exception has been thrown.
888 Note: synchronized with global tablelock
890 *******************************************************************************/
892 bool classcache_store_unique(classinfo *cls)
896 result = classcache_store(NULL,cls,false);
901 exceptions_throw_internalerror("class already stored in the class cache");
908 /* classcache_store_defined ****************************************************
910 Store a loaded class after it has been defined. If the class has already
911 been defined by the same defining loader in another thread, free the given
912 class and returned the one which has been defined earlier.
915 cls..............class object to store. classloader must be set
916 (classloader may be NULL, for bootloader)
919 cls..............everything ok, the class was stored the cache,
920 other classinfo..the class had already been defined, CLS was freed, the
921 class which was defined earlier is returned,
922 NULL.............an exception has been thrown.
924 *******************************************************************************/
926 classinfo *classcache_store_defined(classinfo *cls)
928 classcache_name_entry *en;
929 classcache_class_entry *clsen;
930 #ifdef CLASSCACHE_VERBOSE
931 char logbuffer[1024];
935 assert(cls->state & CLASS_LOADED);
939 #ifdef CLASSCACHE_VERBOSE
940 sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
941 utf_cat_classname(logbuffer, cls->name);
942 strcat(logbuffer,")");
943 log_println(logbuffer);
946 en = classcache_new_name(cls->name);
950 /* iterate over all class entries */
951 for (clsen = en->classes; clsen; clsen = clsen->next) {
953 /* check if this class has been defined by the same classloader */
954 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
955 /* we found an earlier definition, delete the newer one */
956 /* (if it is a different classinfo) */
957 if (clsen->classobj != cls) {
958 #ifdef CLASSCACHE_VERBOSE
959 log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
962 cls = clsen->classobj;
968 /* create a new class entry for this class object */
969 /* the list of initiating loaders is empty at this point */
971 clsen = NEW(classcache_class_entry);
972 clsen->classobj = cls;
973 clsen->loaders = NULL;
974 clsen->constraints = NULL;
976 clsen->next = en->classes;
978 CLASSCACHE_COUNT(stat_classes_stored);
981 #ifdef CLASSCACHE_VERBOSE
982 classcache_debug_dump(stdout,cls->name);
988 /* classcache_find_loader ******************************************************
990 Find the class entry loaded by or constrained to a given loader
991 (internally used helper function)
994 entry............the classcache_name_entry
995 loader...........the loader to look for
998 the classcache_class_entry for the given loader, or
999 NULL if no entry was found
1001 *******************************************************************************/
1003 static classcache_class_entry * classcache_find_loader(
1004 classcache_name_entry * entry,
1005 classloader_t * loader)
1007 classcache_class_entry *clsen;
1008 classcache_loader_entry *lden;
1012 /* iterate over all class entries */
1013 for (clsen = entry->classes; clsen; clsen = clsen->next) {
1015 /* check if this entry has already been loaded by initloader */
1016 for (lden = clsen->loaders; lden; lden = lden->next) {
1017 if (lden->loader == loader)
1018 return clsen; /* found */
1021 /* check if loader is constrained to this entry */
1022 for (lden = clsen->constraints; lden; lden = lden->next) {
1023 if (lden->loader == loader)
1024 return clsen; /* found */
1032 /* classcache_free_class_entry *************************************************
1034 Free the memory used by a class entry
1037 clsen............the classcache_class_entry to free
1039 *******************************************************************************/
1041 static void classcache_free_class_entry(classcache_class_entry * clsen)
1043 classcache_loader_entry *lden;
1044 classcache_loader_entry *next;
1048 for (lden = clsen->loaders; lden; lden = next) {
1050 FREE(lden, classcache_loader_entry);
1052 for (lden = clsen->constraints; lden; lden = next) {
1054 FREE(lden, classcache_loader_entry);
1057 FREE(clsen, classcache_class_entry);
1060 /* classcache_remove_class_entry ***********************************************
1062 Remove a classcache_class_entry from the list of possible resolution of
1064 (internally used helper function)
1067 entry............the classcache_name_entry
1068 clsen............the classcache_class_entry to remove
1070 *******************************************************************************/
1072 static void classcache_remove_class_entry(classcache_name_entry * entry,
1073 classcache_class_entry * clsen)
1075 classcache_class_entry **chain;
1080 chain = &(entry->classes);
1082 if (*chain == clsen) {
1083 *chain = clsen->next;
1084 classcache_free_class_entry(clsen);
1087 chain = &((*chain)->next);
1091 /* classcache_free_name_entry **************************************************
1093 Free the memory used by a name entry
1096 entry............the classcache_name_entry to free
1098 *******************************************************************************/
1100 static void classcache_free_name_entry(classcache_name_entry * entry)
1102 classcache_class_entry *clsen;
1103 classcache_class_entry *next;
1107 for (clsen = entry->classes; clsen; clsen = next) {
1109 classcache_free_class_entry(clsen);
1112 FREE(entry, classcache_name_entry);
1115 /* classcache_free *************************************************************
1117 Free the memory used by the class cache
1120 The class cache may not be used any more after this call, except
1121 when it is reinitialized with classcache_init.
1123 Note: NOT synchronized!
1125 *******************************************************************************/
1127 void classcache_free(void)
1130 classcache_name_entry *entry;
1131 classcache_name_entry *next;
1133 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1134 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1135 next = entry->hashlink;
1136 classcache_free_name_entry(entry);
1140 MFREE(hashtable_classcache.ptr, void*, hashtable_classcache.size);
1141 hashtable_classcache.size = 0;
1142 hashtable_classcache.entries = 0;
1143 hashtable_classcache.ptr = NULL;
1146 /* classcache_add_constraint ***************************************************
1148 Add a loading constraint
1151 a................first initiating loader
1152 b................second initiating loader
1153 classname........class name
1156 true.............everything ok, the constraint has been added,
1157 false............an exception has been thrown.
1159 Note: synchronized with global tablelock
1161 *******************************************************************************/
1163 #if defined(ENABLE_VERIFIER)
1164 bool classcache_add_constraint(classloader_t * a,
1168 classcache_name_entry *en;
1169 classcache_class_entry *clsenA;
1170 classcache_class_entry *clsenB;
1174 #ifdef CLASSCACHE_VERBOSE
1176 log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1177 utf_fprint_printable_ascii_classname(stdout, classname);
1182 /* a constraint with a == b is trivially satisfied */
1184 CLASSCACHE_COUNT(stat_trivial_constraints);
1190 en = classcache_new_name(classname);
1193 CLASSCACHE_COUNT(stat_nontriv_constraints);
1195 /* find the entry loaded by / constrained to each loader */
1196 clsenA = classcache_find_loader(en, a);
1197 clsenB = classcache_find_loader(en, b);
1199 if (clsenA && clsenB) {
1200 /* { both loaders have corresponding entries } */
1201 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1203 /* if the entries are the same, the constraint is already recorded */
1204 if (clsenA == clsenB)
1205 goto return_success;
1207 /* check if the entries can be merged */
1208 if (clsenA->classobj && clsenB->classobj
1209 && clsenA->classobj != clsenB->classobj) {
1210 /* no, the constraint is violated */
1211 exceptions_throw_linkageerror("loading constraint violated: ",
1213 goto return_exception;
1216 /* yes, merge the entries */
1217 classcache_merge_class_entries(en,clsenA,clsenB);
1218 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1221 /* { at most one of the loaders has a corresponding entry } */
1223 /* set clsenA to the single class entry we have */
1228 /* { no loader has a corresponding entry } */
1229 CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1231 /* create a new class entry with the constraint (a,b,en->name) */
1232 clsenA = NEW(classcache_class_entry);
1233 clsenA->classobj = NULL;
1234 clsenA->loaders = NULL;
1235 clsenA->constraints = classcache_new_loader_entry(b, NULL);
1236 clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1238 clsenA->next = en->classes;
1239 en->classes = clsenA;
1242 CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1244 /* make b the loader that has no corresponding entry */
1248 /* loader b must be added to entry clsenA */
1249 clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1254 CLASSCACHE_UNLOCK();
1258 CLASSCACHE_UNLOCK();
1259 return false; /* exception */
1261 #endif /* defined(ENABLE_VERIFIER) */
1263 /* classcache_add_constraints_for_params ***************************************
1265 Add loading constraints for the parameters and return type of
1269 a................first initiating loader
1270 b................second initiating loader
1271 m................methodinfo
1274 true.............everything ok, the constraints have been added,
1275 false............an exception has been thrown.
1277 Note: synchronized with global tablelock
1279 *******************************************************************************/
1281 #if defined(ENABLE_VERIFIER)
1282 bool classcache_add_constraints_for_params(classloader_t * a,
1290 /* a constraint with a == b is trivially satisfied */
1296 /* get the parsed descriptor */
1302 /* constrain the return type */
1304 if (md->returntype.type == TYPE_ADR) {
1305 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1306 return false; /* exception */
1309 /* constrain each reference type used in the parameters */
1311 td = md->paramtypes;
1314 if (td->type != TYPE_ADR)
1317 if (!classcache_add_constraint(a, b, td->classref->name))
1318 return false; /* exception */
1324 #endif /* defined(ENABLE_VERIFIER) */
1327 /* classcache_number_of_loaded_classes *****************************************
1329 Counts the number of loaded classes and returns it.
1331 Note: This function assumes that the CLASSCACHE_LOCK is held by the
1334 *******************************************************************************/
1336 static s4 classcache_number_of_loaded_classes(void)
1338 classcache_name_entry *en;
1339 classcache_class_entry *clsen;
1343 /* initialize class counter */
1347 for (i = 0; i < hashtable_classcache.size; i++) {
1348 /* iterate over hashlink */
1350 for (en = (classcache_name_entry*) hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1351 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1353 if (en->name->text[0] == '$')
1356 /* iterate over classes with same name */
1358 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1359 /* get only loaded classes */
1361 if (clsen->classobj != NULL)
1371 /* classcache_get_loaded_class_count *******************************************
1373 Counts the number of loaded classes and returns it.
1375 *******************************************************************************/
1377 s4 classcache_get_loaded_class_count(void)
1383 count = classcache_number_of_loaded_classes();
1385 CLASSCACHE_UNLOCK();
1391 /* classcache_foreach_loaded_class *********************************************
1393 Calls the given function for each loaded class.
1395 *******************************************************************************/
1397 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1400 classcache_name_entry *en;
1401 classcache_class_entry *clsen;
1406 /* look in every slot of the hashtable */
1408 for (i = 0; i < hashtable_classcache.size; i++) {
1409 /* iterate over hashlink */
1411 for (en = (classcache_name_entry*) hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1412 /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1414 if (en->name->text[0] == '$')
1417 /* iterate over classes with same name */
1419 for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1420 /* get only loaded classes */
1422 if (clsen->classobj != NULL) {
1423 (*func)(clsen->classobj, data);
1429 CLASSCACHE_UNLOCK();
1433 /*============================================================================*/
1435 /*============================================================================*/
1437 /* classcache_debug_dump *******************************************************
1439 Print the contents of the loaded class cache to a stream
1442 file.............output stream
1443 only.............if != NULL, only print entries for this name
1444 (Currently we print also the rest of the hash chain to
1445 get a feel for the average length of hash chains.)
1447 Note: synchronized with global tablelock
1449 *******************************************************************************/
1452 void classcache_debug_dump(FILE * file,utf *only)
1454 classcache_name_entry *c;
1455 classcache_class_entry *clsen;
1456 classcache_loader_entry *lden;
1461 log_println("=== [loaded class cache] =====================================");
1462 log_println("hash size : %d", (int) hashtable_classcache.size);
1463 log_println("hash entries: %d", (int) hashtable_classcache.entries);
1467 c = classcache_lookup_name(only);
1468 slot = 0; /* avoid compiler warning */
1472 for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1473 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1476 for (; c; c = c->hashlink) {
1477 utf_fprint_printable_ascii_classname(file, c->name);
1478 fprintf(file, "\n");
1480 /* iterate over all class entries */
1481 for (clsen = c->classes; clsen; clsen = clsen->next) {
1482 if (clsen->classobj) {
1483 log_println(" loaded %p", (void *) clsen->classobj);
1486 log_println(" unresolved");
1490 log_print(" loaders: ");
1491 for (lden = clsen->loaders; lden; lden = lden->next) {
1492 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1497 log_print(" constraints: ");
1498 for (lden = clsen->constraints; lden; lden = lden->next) {
1499 log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1508 fprintf(file, "\n==============================================================\n\n");
1510 CLASSCACHE_UNLOCK();
1516 * These are local overrides for various environment variables in Emacs.
1517 * Please do not remove this and leave it at the end of the file, where
1518 * Emacs will automagically detect them.
1519 * ---------------------------------------------------------------------
1522 * indent-tabs-mode: t
1526 * vim:noexpandtab:sw=4:ts=4: