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