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