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