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