27013ef2fc7abc9f639e1e68f83cc8d755be4f22
[cacao.git] / src / vmcore / classcache.c
1 /* src/vmcore/classcache.c - loaded class cache and loading constraints
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02110-1301, USA.
24
25    $Id: classcache.c 8295 2007-08-11 17:57:24Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37
38 #include "threads/lock-common.h"
39
40 #include "toolbox/hashtable.h"
41 #include "toolbox/logging.h"
42
43 #include "vm/exceptions.h"
44
45 #include "vmcore/classcache.h"
46 #include "vmcore/utf8.h"
47
48
49 /*************************************************************************
50
51   Class Cache
52
53   The classcache has two functions:
54   
55         1) caching the resolution of class references
56         2) storing and checking loading constraints
57
58   We will use the following terms in this description:
59
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
64                                 C = *(N,L)
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
67                                 *(N,L1) = *(N,L2)
68
69   The functions of the classcache require:
70
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) }
73
74   These functions can be rearranged like that:
75
76     a mapping N |--> (a mapping L |--> C or NULL, 
77                           a set of constraints {(L1,L2)})
78
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.
83
84   For a class name N we can define an equivalence relation ~N~ on
85   class loaders:
86
87         L1 ~N~ L2  <==>  *(N,L1) = *(N,L2)
88
89   A loading constraint (N,L1,L2) implies L1 ~N~ L2.
90
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].
94
95   A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
96   where
97                 Cx...is a class C or NULL
98                 IL...is the set of initiating loaders
99                 CL...is the set of constrained loaders
100                 
101   Such a tuple is called `classcache_class_entry` in the source code.
102
103   The following holds for each tuple (Cx,IL,CL):
104
105     .  (Cx is NULL) implies IL = {}.
106            
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.
111   
112     .  (IL u CL) is a subset of an equivalence class of ~N~.
113
114                  (This means that all loaders in IL and CL must resolve
115                  the name N to the same class.)
116
117   The following holds for the set of tuples { (Cx,IL,CL) }:
118
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.)
122
123         .  For a given loader L there is at most one tuple with
124            L in (IL u CL).
125
126   The implementation stores sets of loaders as linked lists of
127   `classcache_loader_entry`s.
128
129   Comments about manipulating the classcache can be found in the
130   individual functions below.
131  
132 *************************************************************************/
133
134
135 /* initial number of slots in the classcache hash table */
136 #define CLASSCACHE_INIT_SIZE  2048
137
138 /*============================================================================*/
139 /* DEBUG HELPERS                                                              */
140 /*============================================================================*/
141
142 /* #define CLASSCACHE_VERBOSE */
143
144 /*============================================================================*/
145 /* STATISTICS                                                                 */
146 /*============================================================================*/
147
148 /*#define CLASSCACHE_STATS*/
149
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;
173
174 #define CLASSCACHE_COUNT(cnt)  (cnt)++
175 #define CLASSCACHE_COUNTIF(cond,cnt)  do{if(cond) (cnt)++;} while(0)
176
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);
200 }
201 #else
202 #define CLASSCACHE_COUNT(cnt)
203 #define CLASSCACHE_COUNTIF(cond,cnt)
204 #endif
205
206 /*============================================================================*/
207 /* THREAD-SAFE LOCKING                                                        */
208 /*============================================================================*/
209
210         /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
211         /* CAUTION: The static functions below are */
212         /*          NOT synchronized!              */
213         /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
214
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)
218 #else
219 # define CLASSCACHE_LOCK()
220 # define CLASSCACHE_UNLOCK()
221 #endif
222
223 /*============================================================================*/
224 /* GLOBAL VARIABLES                                                           */
225 /*============================================================================*/
226
227 hashtable hashtable_classcache;
228
229 #if defined(ENABLE_THREADS)
230 static java_object_t *lock_hashtable_classcache;
231 #endif
232
233
234 /*============================================================================*/
235 /*                                                                            */
236 /*============================================================================*/
237
238 /* prototypes */
239
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);
243
244 /* hash function to use */
245
246 #define CLASSCACHE_HASH utf_full_hashkey
247
248 /* classcache_init *************************************************************
249  
250    Initialize the class cache
251
252    Note: NOT synchronized!
253   
254 *******************************************************************************/
255
256 bool classcache_init(void)
257 {
258         /* create the hashtable */
259
260         hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
261
262 #if defined(ENABLE_THREADS)
263         /* create utf hashtable lock object */
264
265         lock_hashtable_classcache = NEW(java_object_t);
266
267         LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
268 #endif
269
270         /* everything's ok */
271
272         return true;
273 }
274
275 /* classcache_new_loader_entry *************************************************
276  
277    Create a new classcache_loader_entry struct
278    (internally used helper function)
279   
280    IN:
281        loader...........the ClassLoader object
282            next.............the next classcache_loader_entry
283
284    RETURN VALUE:
285        the new classcache_loader_entry
286   
287 *******************************************************************************/
288
289 static classcache_loader_entry * classcache_new_loader_entry(
290                                                                         classloader * loader,
291                                                                         classcache_loader_entry * next)
292 {
293         classcache_loader_entry *lden;
294
295         lden = NEW(classcache_loader_entry);
296         lden->loader = loader;
297         lden->next = next;
298         CLASSCACHE_COUNT(stat_new_loader_entry);
299
300         return lden;
301 }
302
303 /* classcache_merge_loaders ****************************************************
304  
305    Merge two lists of loaders into one
306    (internally used helper function)
307   
308    IN:
309        lista............first list (may be NULL)
310            listb............second list (may be NULL)
311
312    RETURN VALUE:
313        the merged list (may be NULL)
314
315    NOTE:
316        The lists given as arguments are destroyed!
317   
318 *******************************************************************************/
319
320 static classcache_loader_entry * classcache_merge_loaders(
321                                                                         classcache_loader_entry * lista,
322                                                                         classcache_loader_entry * listb)
323 {
324         classcache_loader_entry *result;
325         classcache_loader_entry *ldenA;
326         classcache_loader_entry *ldenB;
327         classcache_loader_entry **chain;
328
329         CLASSCACHE_COUNT(stat_merge_loader_entries);
330
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. */
334
335         result = NULL;
336         chain = &result;
337
338         for (ldenA = lista; ldenA; ldenA = ldenA->next) {
339
340                 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
341                         if (ldenB->loader == ldenA->loader)
342                                 goto common_element;
343                 }
344
345                 /* this loader is only in lista */
346                 *chain = ldenA;
347                 chain = &(ldenA->next);
348
349           common_element:
350                 /* XXX free the duplicated element */
351                 ;
352         }
353
354         /* concat listb to the result */
355         *chain = listb;
356
357         return result;
358 }
359
360 /* classcache_merge_class_entries **********************************************
361  
362    Merge two `classcache_class_entry`s into one.
363    (internally used helper function)
364   
365    IN:
366        en...............the classcache_name_entry containing both class entries
367        clsenA...........first class entry, will receive the result
368            clsenB...........second class entry
369
370    PRE-CONDITION:
371        Either both entries must have the same classobj, or one of them has
372            classobj == NULL.
373
374    NOTE:
375        clsenB is freed by this function!
376   
377 *******************************************************************************/
378
379 static void classcache_merge_class_entries(classcache_name_entry *en,
380                                                                                    classcache_class_entry *clsenA,
381                                                                                    classcache_class_entry *clsenB)
382 {
383 #ifdef CLASSCACHE_VERBOSE
384         char logbuffer[1024];
385 #endif
386         
387         assert(en);
388         assert(clsenA);
389         assert(clsenB);
390         assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
391
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);
400 #endif
401
402         CLASSCACHE_COUNT(stat_merge_class_entries);
403
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 */
407
408         clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
409                                                                                                    clsenB->constraints);
410         clsenB->constraints = NULL; /* these have been freed or reused */
411
412         if (!clsenA->classobj)
413                 clsenA->classobj = clsenB->classobj;
414
415         /* remove clsenB from the list of class entries */
416         classcache_remove_class_entry(en, clsenB);
417 }
418
419
420 /* classcache_lookup_name ******************************************************
421  
422    Lookup a name in the first level of the cache
423    (internally used helper function)
424    
425    IN:
426        name.............the name to look up
427   
428    RETURN VALUE:
429        a pointer to the classcache_name_entry for this name, or
430        null if no entry was found.
431            
432 *******************************************************************************/
433
434 static classcache_name_entry *classcache_lookup_name(utf *name)
435 {
436         classcache_name_entry *c;           /* hash table element                 */
437         u4 key;                             /* hashkey computed from classname    */
438         u4 slot;                            /* slot in hashtable                  */
439
440         CLASSCACHE_COUNT(stat_lookup_name);
441
442         key  = CLASSCACHE_HASH(name->text, (u4) name->blength);
443         slot = key & (hashtable_classcache.size - 1);
444         c    = hashtable_classcache.ptr[slot];
445
446         /* search external hash chain for the entry */
447
448         while (c) {
449                 /* entry found in hashtable */
450                 CLASSCACHE_COUNT(stat_lookup_name_entry);
451
452                 if (c->name == name)
453                         return c;
454
455                 c = c->hashlink;                    /* next element in external chain */
456         }
457
458         /* not found */
459
460         CLASSCACHE_COUNT(stat_lookup_name_notfound);
461         return NULL;
462 }
463
464
465 /* classcache_new_name *********************************************************
466  
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)
470    
471    IN:
472        name.............the name to look up / create an entry for
473   
474    RETURN VALUE:
475        a pointer to the classcache_name_entry for this name
476            
477 *******************************************************************************/
478
479 static classcache_name_entry *classcache_new_name(utf *name)
480 {
481         classcache_name_entry *c;       /* hash table element */
482         u4 key;                                         /* hashkey computed from classname */
483         u4 slot;                                        /* slot in hashtable               */
484         u4 i;
485
486         CLASSCACHE_COUNT(stat_lookup_new_name);
487
488         key  = CLASSCACHE_HASH(name->text, (u4) name->blength);
489         slot = key & (hashtable_classcache.size - 1);
490         c    = hashtable_classcache.ptr[slot];
491
492         /* search external hash chain for the entry */
493
494         while (c) {
495                 /* entry found in hashtable */
496                 CLASSCACHE_COUNT(stat_lookup_new_name_entry);
497
498                 if (c->name == name)
499                         return c;
500
501                 c = c->hashlink;                    /* next element in external chain */
502         }
503
504         /* location in hashtable found, create new entry */
505
506         c = NEW(classcache_name_entry);
507
508         c->name = name;
509         c->classes = NULL;
510
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;
515
516         /* update number of hashtable-entries */
517         hashtable_classcache.entries++;
518         CLASSCACHE_COUNT(stat_classnames_stored);
519
520         if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
521                 /* reorganization of hashtable */ 
522
523                 classcache_name_entry *c2;
524                 hashtable newhash;              /* the new hashtable */
525
526                 CLASSCACHE_COUNT(stat_rehash_names);
527
528                 /* create new hashtable, double the size */
529
530                 hashtable_create(&newhash, hashtable_classcache.size * 2);
531                 newhash.entries = hashtable_classcache.entries;
532
533                 /* transfer elements to new hashtable */
534
535                 for (i = 0; i < hashtable_classcache.size; i++) {
536                         c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
537                         while (c2) {
538                                 classcache_name_entry *nextc = c2->hashlink;
539                                 u4 newslot =
540                                         (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
541
542                                 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
543                                 CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
544                                 newhash.ptr[newslot] = c2;
545
546                                 c2 = nextc;
547                         }
548                 }
549
550                 /* dispose old table */
551
552                 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
553                 hashtable_classcache = newhash;
554         }
555
556         return c;
557 }
558
559
560 /* classcache_lookup ***********************************************************
561  
562    Lookup a possibly loaded class
563   
564    IN:
565        initloader.......initiating loader for resolving the class name
566        classname........class name to look up
567   
568    RETURN VALUE:
569        The return value is a pointer to the cached class object,
570        or NULL, if the class is not in the cache.
571
572    Note: synchronized with global tablelock
573    
574 *******************************************************************************/
575
576 classinfo *classcache_lookup(classloader *initloader, utf *classname)
577 {
578         classcache_name_entry *en;
579         classcache_class_entry *clsen;
580         classcache_loader_entry *lden;
581         classinfo *cls = NULL;
582
583         CLASSCACHE_LOCK();
584
585         CLASSCACHE_COUNT(stat_lookup);
586         en = classcache_lookup_name(classname);
587
588         if (en) {
589                 /* iterate over all class entries */
590
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 */
594
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 */
599
600                                         assert(clsen->classobj);
601                                         cls = clsen->classobj;
602                                         goto found;
603                                 }
604                         }
605                 }
606         }
607
608   found:
609         CLASSCACHE_UNLOCK();
610         return cls;
611 }
612
613
614 /* classcache_lookup_defined ***************************************************
615  
616    Lookup a class with the given name and defining loader
617   
618    IN:
619        defloader........defining loader
620        classname........class name
621   
622    RETURN VALUE:
623        The return value is a pointer to the cached class object,
624        or NULL, if the class is not in the cache.
625    
626 *******************************************************************************/
627
628 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
629 {
630         classcache_name_entry *en;
631         classcache_class_entry *clsen;
632         classinfo *cls = NULL;
633
634         CLASSCACHE_LOCK();
635
636         en = classcache_lookup_name(classname);
637
638         if (en) {
639                 /* iterate over all class entries */
640                 for (clsen = en->classes; clsen; clsen = clsen->next) {
641                         if (!clsen->classobj)
642                                 continue;
643
644                         /* check if this entry has been defined by defloader */
645                         if (clsen->classobj->classloader == defloader) {
646                                 cls = clsen->classobj;
647                                 goto found;
648                         }
649                 }
650         }
651
652   found:
653         CLASSCACHE_UNLOCK();
654         return cls;
655 }
656
657
658 /* classcache_lookup_defined_or_initiated **************************************
659  
660    Lookup a class that has been defined or initiated by the given loader
661   
662    IN:
663        loader...........defining or initiating loader
664        classname........class name to look up
665   
666    RETURN VALUE:
667        The return value is a pointer to the cached class object,
668        or NULL, if the class is not in the cache.
669
670    Note: synchronized with global tablelock
671    
672 *******************************************************************************/
673
674 classinfo *classcache_lookup_defined_or_initiated(classloader *loader, 
675                                                                                                   utf *classname)
676 {
677         classcache_name_entry *en;
678         classcache_class_entry *clsen;
679         classcache_loader_entry *lden;
680         classinfo *cls = NULL;
681
682         CLASSCACHE_LOCK();
683
684         en = classcache_lookup_name(classname);
685
686         if (en) {
687                 /* iterate over all class entries */
688
689                 for (clsen = en->classes; clsen; clsen = clsen->next) {
690
691                         /* check if this entry has been defined by loader */
692                         if (clsen->classobj && clsen->classobj->classloader == loader) {
693                                 cls = clsen->classobj;
694                                 goto found;
695                         }
696                         
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 */
701
702                                         assert(clsen->classobj);
703                                         cls = clsen->classobj;
704                                         goto found;
705                                 }
706                         }
707                 }
708         }
709
710   found:
711         CLASSCACHE_UNLOCK();
712         return cls;
713 }
714
715
716 /* classcache_store ************************************************************
717    
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.
721   
722    IN:
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
727                             returned
728   
729    RETURN VALUE:
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.
735    
736    Note: synchronized with global tablelock
737
738    [1]...in case MAYFREE is true
739    
740 *******************************************************************************/
741
742 classinfo *classcache_store(classloader *initloader, classinfo *cls,
743                                                         bool mayfree)
744 {
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];
751 #endif
752         
753         assert(cls);
754         assert(cls->state & CLASS_LOADED);
755
756         CLASSCACHE_LOCK();
757
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);
763 #endif
764
765         en = classcache_new_name(cls->name);
766
767         assert(en);
768
769         /* iterate over all class entries */
770         for (clsen = en->classes; clsen; clsen = clsen->next) {
771
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);
780 #endif
781                                         assert(clsen->classobj);
782                                         if (mayfree)
783                                                 class_free(cls);
784                                         cls = clsen->classobj;
785                            }
786                            goto return_success;
787                         }
788                 }
789
790                 /* {This entry has not been resolved with initloader} */
791
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;
802                                         }
803
804                                         /* record initloader as initiating loader */
805                                         clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
806                                         goto return_success;
807                                 }
808
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);
812
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);
819                                                 goto return_success;
820                                         }
821                                 }
822
823                                 /* record the loaded class object */
824                                 clsen->classobj = cls;
825                                 CLASSCACHE_COUNT(stat_classes_stored);
826
827                                 /* done */
828                                 goto return_success;
829                         }
830                 }
831
832         }
833
834         /* {There is no class entry containing initloader as initiating 
835          *  or constrained loader.} */
836
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)
844                                         goto return_success;
845                         }
846                         clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
847                         goto return_success;
848                 }
849         }
850
851         /* create a new class entry for this class object with */
852         /* initiating loader initloader                        */
853
854         clsen = NEW(classcache_class_entry);
855         clsen->classobj = cls;
856         clsen->loaders = classcache_new_loader_entry(initloader, NULL);
857         clsen->constraints = NULL;
858
859         clsen->next = en->classes;
860         en->classes = clsen;
861         CLASSCACHE_COUNT(stat_classes_stored);
862
863   return_success:
864 #ifdef CLASSCACHE_VERBOSE
865         classcache_debug_dump(stdout,cls->name);
866 #endif
867         CLASSCACHE_UNLOCK();
868         return cls;
869
870   return_exception:
871         CLASSCACHE_UNLOCK();
872         return NULL;                            /* exception */
873 }
874
875 /* classcache_store_unique *****************************************************
876    
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.
880
881    This function is used to register a few special classes during startup.
882    It should not be used otherwise.
883   
884    IN:
885        cls..............class object to cache
886   
887    RETURN VALUE:
888        true.............everything ok, the class was stored.
889        false............an exception has been thrown.
890    
891    Note: synchronized with global tablelock
892    
893 *******************************************************************************/
894
895 bool classcache_store_unique(classinfo *cls)
896 {
897         classinfo *result;
898
899         result = classcache_store(NULL,cls,false);
900         if (result == NULL)
901                 return false;
902
903         if (result != cls) {
904                 exceptions_throw_internalerror("class already stored in the class cache");
905                 return false;
906         }
907
908         return true;
909 }
910
911 /* classcache_store_defined ****************************************************
912    
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.
916   
917    IN:
918        cls..............class object to store. classloader must be set
919                             (classloader may be NULL, for bootloader)
920   
921    RETURN VALUE:
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.
926    
927 *******************************************************************************/
928
929 classinfo *classcache_store_defined(classinfo *cls)
930 {
931         classcache_name_entry *en;
932         classcache_class_entry *clsen;
933 #ifdef CLASSCACHE_VERBOSE
934         char logbuffer[1024];
935 #endif
936
937         assert(cls);
938         assert(cls->state & CLASS_LOADED);
939
940         CLASSCACHE_LOCK();
941
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);
947 #endif
948
949         en = classcache_new_name(cls->name);
950
951         assert(en);
952
953         /* iterate over all class entries */
954         for (clsen = en->classes; clsen; clsen = clsen->next) {
955                 
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);
963 #endif
964                                 class_free(cls);
965                                 cls = clsen->classobj;
966                         }
967                         goto return_success;
968                 }
969         }
970
971         /* create a new class entry for this class object */
972         /* the list of initiating loaders is empty at this point */
973
974         clsen = NEW(classcache_class_entry);
975         clsen->classobj = cls;
976         clsen->loaders = NULL;
977         clsen->constraints = NULL;
978
979         clsen->next = en->classes;
980         en->classes = clsen;
981         CLASSCACHE_COUNT(stat_classes_stored);
982
983 return_success:
984 #ifdef CLASSCACHE_VERBOSE
985         classcache_debug_dump(stdout,cls->name);
986 #endif
987         CLASSCACHE_UNLOCK();
988         return cls;
989 }
990
991 /* classcache_find_loader ******************************************************
992  
993    Find the class entry loaded by or constrained to a given loader
994    (internally used helper function)
995   
996    IN:
997        entry............the classcache_name_entry
998        loader...........the loader to look for
999   
1000    RETURN VALUE:
1001        the classcache_class_entry for the given loader, or
1002            NULL if no entry was found
1003    
1004 *******************************************************************************/
1005
1006 static classcache_class_entry * classcache_find_loader(
1007                                                                         classcache_name_entry * entry,
1008                                                                         classloader * loader)
1009 {
1010         classcache_class_entry *clsen;
1011         classcache_loader_entry *lden;
1012
1013         assert(entry);
1014
1015         /* iterate over all class entries */
1016         for (clsen = entry->classes; clsen; clsen = clsen->next) {
1017
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 */
1022                 }
1023
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 */
1028                 }
1029         }
1030
1031         /* not found */
1032         return NULL;
1033 }
1034
1035 /* classcache_free_class_entry *************************************************
1036  
1037    Free the memory used by a class entry
1038   
1039    IN:
1040        clsen............the classcache_class_entry to free  
1041            
1042 *******************************************************************************/
1043
1044 static void classcache_free_class_entry(classcache_class_entry * clsen)
1045 {
1046         classcache_loader_entry *lden;
1047         classcache_loader_entry *next;
1048
1049         assert(clsen);
1050
1051         for (lden = clsen->loaders; lden; lden = next) {
1052                 next = lden->next;
1053                 FREE(lden, classcache_loader_entry);
1054         }
1055         for (lden = clsen->constraints; lden; lden = next) {
1056                 next = lden->next;
1057                 FREE(lden, classcache_loader_entry);
1058         }
1059
1060         FREE(clsen, classcache_class_entry);
1061 }
1062
1063 /* classcache_remove_class_entry ***********************************************
1064  
1065    Remove a classcache_class_entry from the list of possible resolution of
1066    a name entry
1067    (internally used helper function)
1068   
1069    IN:
1070        entry............the classcache_name_entry
1071        clsen............the classcache_class_entry to remove
1072   
1073 *******************************************************************************/
1074
1075 static void classcache_remove_class_entry(classcache_name_entry * entry,
1076                                                                                   classcache_class_entry * clsen)
1077 {
1078         classcache_class_entry **chain;
1079
1080         assert(entry);
1081         assert(clsen);
1082
1083         chain = &(entry->classes);
1084         while (*chain) {
1085                 if (*chain == clsen) {
1086                         *chain = clsen->next;
1087                         classcache_free_class_entry(clsen);
1088                         return;
1089                 }
1090                 chain = &((*chain)->next);
1091         }
1092 }
1093
1094 /* classcache_free_name_entry **************************************************
1095  
1096    Free the memory used by a name entry
1097   
1098    IN:
1099        entry............the classcache_name_entry to free  
1100            
1101 *******************************************************************************/
1102
1103 static void classcache_free_name_entry(classcache_name_entry * entry)
1104 {
1105         classcache_class_entry *clsen;
1106         classcache_class_entry *next;
1107
1108         assert(entry);
1109
1110         for (clsen = entry->classes; clsen; clsen = next) {
1111                 next = clsen->next;
1112                 classcache_free_class_entry(clsen);
1113         }
1114
1115         FREE(entry, classcache_name_entry);
1116 }
1117
1118 /* classcache_free *************************************************************
1119  
1120    Free the memory used by the class cache
1121
1122    NOTE:
1123        The class cache may not be used any more after this call, except
1124            when it is reinitialized with classcache_init.
1125   
1126    Note: NOT synchronized!
1127   
1128 *******************************************************************************/
1129
1130 void classcache_free(void)
1131 {
1132         u4 slot;
1133         classcache_name_entry *entry;
1134         classcache_name_entry *next;
1135
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);
1140                 }
1141         }
1142
1143         MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
1144         hashtable_classcache.size = 0;
1145         hashtable_classcache.entries = 0;
1146         hashtable_classcache.ptr = NULL;
1147 }
1148
1149 /* classcache_add_constraint ***************************************************
1150  
1151    Add a loading constraint
1152   
1153    IN:
1154        a................first initiating loader
1155        b................second initiating loader
1156        classname........class name
1157   
1158    RETURN VALUE:
1159        true.............everything ok, the constraint has been added,
1160        false............an exception has been thrown.
1161    
1162    Note: synchronized with global tablelock
1163    
1164 *******************************************************************************/
1165
1166 #if defined(ENABLE_VERIFIER)
1167 bool classcache_add_constraint(classloader * a,
1168                                                            classloader * b,
1169                                                            utf * classname)
1170 {
1171         classcache_name_entry *en;
1172         classcache_class_entry *clsenA;
1173         classcache_class_entry *clsenB;
1174
1175         assert(classname);
1176
1177 #ifdef CLASSCACHE_VERBOSE
1178         log_start();
1179         log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
1180         utf_fprint_printable_ascii_classname(stdout, classname);
1181         log_print(")\n");
1182         log_finish();
1183 #endif
1184
1185         /* a constraint with a == b is trivially satisfied */
1186         if (a == b) {
1187                 CLASSCACHE_COUNT(stat_trivial_constraints);
1188                 return true;
1189         }
1190
1191         CLASSCACHE_LOCK();
1192
1193         en = classcache_new_name(classname);
1194
1195         assert(en);
1196         CLASSCACHE_COUNT(stat_nontriv_constraints);
1197
1198         /* find the entry loaded by / constrained to each loader */
1199         clsenA = classcache_find_loader(en, a);
1200         clsenB = classcache_find_loader(en, b);
1201
1202         if (clsenA && clsenB) {
1203                 /* { both loaders have corresponding entries } */
1204                 CLASSCACHE_COUNT(stat_nontriv_constraints_both);
1205
1206                 /* if the entries are the same, the constraint is already recorded */
1207                 if (clsenA == clsenB)
1208                         goto return_success;
1209
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: ",
1215                                                                                   clsenA->classobj);
1216                         goto return_exception;
1217                 }
1218
1219                 /* yes, merge the entries */
1220                 classcache_merge_class_entries(en,clsenA,clsenB);
1221                 CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
1222         }
1223         else {
1224                 /* { at most one of the loaders has a corresponding entry } */
1225
1226                 /* set clsenA to the single class entry we have */
1227                 if (!clsenA)
1228                         clsenA = clsenB;
1229
1230                 if (!clsenA) {
1231                         /* { no loader has a corresponding entry } */
1232                         CLASSCACHE_COUNT(stat_nontriv_constraints_none);
1233
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);
1240
1241                         clsenA->next = en->classes;
1242                         en->classes = clsenA;
1243                 }
1244                 else {
1245                         CLASSCACHE_COUNT(stat_nontriv_constraints_one);
1246
1247                         /* make b the loader that has no corresponding entry */
1248                         if (clsenB)
1249                                 b = a;
1250
1251                         /* loader b must be added to entry clsenA */
1252                         clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1253                 }
1254         }
1255
1256   return_success:
1257         CLASSCACHE_UNLOCK();
1258         return true;
1259
1260   return_exception:
1261         CLASSCACHE_UNLOCK();
1262         return false;                           /* exception */
1263 }
1264 #endif /* defined(ENABLE_VERIFIER) */
1265
1266 /* classcache_add_constraints_for_params ***************************************
1267  
1268    Add loading constraints for the parameters and return type of 
1269    the given method.
1270   
1271    IN:
1272        a................first initiating loader
1273        b................second initiating loader
1274        m................methodinfo 
1275   
1276    RETURN VALUE:
1277        true.............everything ok, the constraints have been added,
1278        false............an exception has been thrown.
1279    
1280    Note: synchronized with global tablelock
1281    
1282 *******************************************************************************/
1283
1284 #if defined(ENABLE_VERIFIER)
1285 bool classcache_add_constraints_for_params(classloader * a,
1286                                                                                    classloader * b,
1287                                                                                    methodinfo *m)
1288 {
1289         methoddesc *md;
1290         typedesc *td;
1291         s4 i;
1292
1293         /* a constraint with a == b is trivially satisfied */
1294
1295         if (a == b) {
1296                 return true;
1297         }
1298
1299         /* get the parsed descriptor */
1300
1301         assert(m);
1302         md = m->parseddesc;
1303         assert(md);
1304
1305         /* constrain the return type */
1306
1307         if (md->returntype.type == TYPE_ADR) {
1308                 if (!classcache_add_constraint(a, b, md->returntype.classref->name))
1309                         return false; /* exception */
1310         }
1311
1312         /* constrain each reference type used in the parameters */
1313
1314         td = md->paramtypes;
1315         i = md->paramcount;
1316         for (; i--; td++) {
1317                 if (td->type != TYPE_ADR)
1318                         continue;
1319
1320                 if (!classcache_add_constraint(a, b, td->classref->name))
1321                         return false; /* exception */
1322         }
1323
1324         /* everything ok */
1325         return true;
1326 }
1327 #endif /* defined(ENABLE_VERIFIER) */
1328
1329
1330 /* classcache_number_of_loaded_classes *****************************************
1331
1332    Counts the number of loaded classes and returns it.
1333
1334    Note: This function assumes that the CLASSCACHE_LOCK is held by the
1335    caller!
1336
1337 *******************************************************************************/
1338
1339 static s4 classcache_number_of_loaded_classes(void)
1340 {
1341         classcache_name_entry  *en;
1342         classcache_class_entry *clsen;
1343         s4                      number;
1344         s4                      i;
1345
1346         /* initialize class counter */
1347
1348         number = 0;
1349
1350         for (i = 0; i < hashtable_classcache.size; i++) {
1351                 /* iterate over hashlink */
1352
1353                 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1354                         /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1355
1356                         if (en->name->text[0] == '$')
1357                                 continue;
1358
1359                         /* iterate over classes with same name */
1360
1361                         for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1362                                 /* get only loaded classes */
1363
1364                                 if (clsen->classobj != NULL)
1365                                         number++;
1366                         }
1367                 }
1368         }
1369
1370         return number;
1371 }
1372
1373
1374 /* classcache_get_loaded_class_count *******************************************
1375
1376    Counts the number of loaded classes and returns it.
1377
1378 *******************************************************************************/
1379
1380 s4 classcache_get_loaded_class_count(void)
1381 {
1382         s4 count;
1383
1384         CLASSCACHE_LOCK();
1385
1386         count = classcache_number_of_loaded_classes();
1387         
1388         CLASSCACHE_UNLOCK();
1389
1390         return count;
1391 }
1392
1393
1394 /* classcache_get_loaded_classes ***********************************************
1395
1396    Returns an array of all loaded classes as array.  The array is
1397    allocaed on the Java heap.
1398
1399 *******************************************************************************/
1400
1401 #if defined(ENABLE_JVMTI)
1402 void classcache_get_loaded_classes(s4 *class_count_ptr,
1403                                                                    classinfo ***classes_ptr)
1404 {
1405         classinfo              **classes;
1406         s4                       class_count;
1407         classcache_name_entry   *en;
1408         classcache_class_entry  *clsen;
1409         s4                       i;
1410         s4                       j;
1411
1412         CLASSCACHE_LOCK();
1413
1414         /* get the number of loaded classes and allocate the array */
1415
1416         class_count = classcache_number_of_loaded_classes();
1417
1418         classes = GCMNEW(classinfo*, class_count);
1419
1420         /* look in every slot of the hashtable */
1421
1422         for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
1423                 /* iterate over hashlink */
1424
1425                 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1426                         /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1427
1428                         if (en->name->text[0] == '$')
1429                                 continue;
1430
1431                         /* iterate over classes with same name */
1432
1433                         for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1434                                 /* get only loaded classes */
1435
1436                                 if (clsen->classobj != NULL) {
1437                                         classes[j] = clsen->classobj;
1438                                         j++;
1439                                 }
1440                         }
1441                 }
1442         }
1443
1444         /* pass the return values */
1445
1446         *class_count_ptr = class_count;
1447         *classes_ptr     = classes;
1448
1449         CLASSCACHE_UNLOCK();
1450 }
1451 #endif /* defined(ENABLE_JVMTI) */
1452
1453
1454 /* classcache_foreach_loaded_class *********************************************
1455
1456    Calls the given function for each loaded class.
1457
1458 *******************************************************************************/
1459
1460 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
1461                                                                          void *data)
1462 {
1463         classcache_name_entry   *en;
1464         classcache_class_entry  *clsen;
1465         s4                       i;
1466
1467         CLASSCACHE_LOCK();
1468
1469         /* look in every slot of the hashtable */
1470
1471         for (i = 0; i < hashtable_classcache.size; i++) {
1472                 /* iterate over hashlink */
1473
1474                 for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1475                         /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1476
1477                         if (en->name->text[0] == '$')
1478                                 continue;
1479
1480                         /* iterate over classes with same name */
1481
1482                         for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1483                                 /* get only loaded classes */
1484
1485                                 if (clsen->classobj != NULL) {
1486                                         (*func)(clsen->classobj, data);
1487                                 }
1488                         }
1489                 }
1490         }
1491
1492         CLASSCACHE_UNLOCK();
1493 }
1494
1495
1496 /*============================================================================*/
1497 /* DEBUG DUMPS                                                                */
1498 /*============================================================================*/
1499
1500 /* classcache_debug_dump *******************************************************
1501  
1502    Print the contents of the loaded class cache to a stream
1503   
1504    IN:
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.)
1509   
1510    Note: synchronized with global tablelock
1511    
1512 *******************************************************************************/
1513
1514 #ifndef NDEBUG
1515 void classcache_debug_dump(FILE * file,utf *only)
1516 {
1517         classcache_name_entry *c;
1518         classcache_class_entry *clsen;
1519         classcache_loader_entry *lden;
1520         u4 slot;
1521
1522         CLASSCACHE_LOCK();
1523
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);
1527         log_println("");
1528
1529         if (only) {
1530                 c = classcache_lookup_name(only);
1531                 slot = 0; /* avoid compiler warning */
1532                 goto dump_it;
1533         }
1534
1535         for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1536                 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1537
1538 dump_it:
1539                 for (; c; c = c->hashlink) {
1540                         utf_fprint_printable_ascii_classname(file, c->name);
1541                         fprintf(file, "\n");
1542
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);
1547                                 }
1548                                 else {
1549                                         log_println("    unresolved");
1550                                 }
1551
1552                                 log_start();
1553                                 log_print("        loaders: ");
1554                                 for (lden = clsen->loaders; lden; lden = lden->next) {
1555                                         log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1556                                 }
1557                                 log_finish();
1558
1559                                 log_start();
1560                                 log_print("        constraints: ");
1561                                 for (lden = clsen->constraints; lden; lden = lden->next) {
1562                                         log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1563                                 }
1564                                 log_finish();
1565                         }
1566                 }
1567
1568                 if (only)
1569                         break;
1570         }
1571         fprintf(file, "\n==============================================================\n\n");
1572
1573         CLASSCACHE_UNLOCK();
1574 }
1575 #endif /* NDEBUG */
1576
1577 /*
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  * ---------------------------------------------------------------------
1582  * Local variables:
1583  * mode: c
1584  * indent-tabs-mode: t
1585  * c-basic-offset: 4
1586  * tab-width: 4
1587  * End:
1588  * vim:noexpandtab:sw=4:ts=4:
1589  */