* vm/tables.h: Renamed to vm/hashtable.h.
[cacao.git] / src / vm / classcache.c
1 /* src/vm/classcache.c - loaded class cache and loading constraints
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Edwin Steiner
28
29    Changes: Christian Thalinger
30
31    $Id: classcache.c 3837 2005-12-01 23:50:28Z twisti $
32
33 */
34
35
36 #include <assert.h>
37
38 #include "config.h"
39 #include "vm/types.h"
40
41 #include "mm/memory.h"
42 #include "vm/classcache.h"
43 #include "vm/exceptions.h"
44 #include "vm/hashtable.h"
45 #include "vm/stringlocal.h"
46 #include "vm/utf8.h"
47
48
49 /* initial number of slots in the classcache hash table */
50 #define CLASSCACHE_INIT_SIZE  2048
51
52 /*============================================================================*/
53 /* DEBUG HELPERS                                                              */
54 /*============================================================================*/
55
56 /*#define CLASSCACHE_VERBOSE*/
57
58 /*============================================================================*/
59 /* THREAD-SAFE LOCKING                                                        */
60 /*============================================================================*/
61
62         /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
63         /* CAUTION: The static functions below are */
64         /*          NOT synchronized!              */
65         /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
66
67 #if defined(USE_THREADS)
68 # define CLASSCACHE_LOCK()      builtin_monitorenter(lock_hashtable_classcache)
69 # define CLASSCACHE_UNLOCK()    builtin_monitorexit(lock_hashtable_classcache)
70 #else
71 # define CLASSCACHE_LOCK()
72 # define CLASSCACHE_UNLOCK()
73 #endif
74
75 /*============================================================================*/
76 /* GLOBAL VARIABLES                                                           */
77 /*============================================================================*/
78
79 hashtable hashtable_classcache;
80
81 #if defined(USE_THREADS)
82 static java_objectheader *lock_hashtable_classcache;
83 #endif
84
85
86 /*============================================================================*/
87 /*                                                                            */
88 /*============================================================================*/
89
90 /* classcache_init *************************************************************
91  
92    Initialize the loaded class cache
93
94    Note: NOT synchronized!
95   
96 *******************************************************************************/
97
98 bool classcache_init(void)
99 {
100         /* create the hashtable */
101
102         hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
103
104 #if defined(USE_THREADS)
105         /* create utf hashtable lock object */
106
107         lock_hashtable_classcache = NEW(java_objectheader);
108
109 # if defined(NATIVE_THREADS)
110         initObjectLock(lock_hashtable_classcache);
111 # endif
112 #endif
113
114         /* everything's ok */
115
116         return true;
117 }
118
119 /* classcache_new_loader_entry *************************************************
120  
121    Create a new classcache_loader_entry struct
122    (internally used helper function)
123   
124    IN:
125        loader...........the ClassLoader object
126            next.............the next classcache_loader_entry
127
128    RETURN VALUE:
129        the new classcache_loader_entry
130   
131 *******************************************************************************/
132
133 static classcache_loader_entry * classcache_new_loader_entry(
134                                                                         classloader * loader,
135                                                                         classcache_loader_entry * next)
136 {
137         classcache_loader_entry *lden;
138
139         lden = NEW(classcache_loader_entry);
140         lden->loader = loader;
141         lden->next = next;
142
143         return lden;
144 }
145
146 /* classcache_merge_loaders ****************************************************
147  
148    Merge two lists of loaders into one
149    (internally used helper function)
150   
151    IN:
152        lista............first list (may be NULL)
153            listb............second list (may be NULL)
154
155    RETURN VALUE:
156        the merged list (may be NULL)
157
158    NOTE:
159        The lists given as arguments are destroyed!
160   
161 *******************************************************************************/
162
163 static classcache_loader_entry * classcache_merge_loaders(
164                                                                         classcache_loader_entry * lista,
165                                                                         classcache_loader_entry * listb)
166 {
167         classcache_loader_entry *result;
168         classcache_loader_entry *ldenA;
169         classcache_loader_entry *ldenB;
170         classcache_loader_entry **chain;
171
172         /* XXX This is a quadratic algorithm. If this ever
173          * becomes a problem, the loader lists should be
174          * stored as sorted lists and merged in linear time. */
175
176         result = NULL;
177         chain = &result;
178
179         for (ldenA = lista; ldenA; ldenA = ldenA->next) {
180
181                 for (ldenB = listb; ldenB; ldenB = ldenB->next) {
182                         if (ldenB->loader == ldenA->loader)
183                                 goto common_element;
184                 }
185
186                 /* this loader is only in lista */
187                 *chain = ldenA;
188                 chain = &(ldenA->next);
189
190           common_element:
191                 /* XXX free the duplicated element */
192                 ;
193         }
194
195         /* concat listb to the result */
196         *chain = listb;
197
198         return result;
199 }
200
201
202 /* classcache_lookup_name ******************************************************
203  
204    Lookup a name in the first level of the cache
205    (internally used helper function)
206    
207    IN:
208        name.............the name to look up
209   
210    RETURN VALUE:
211        a pointer to the classcache_name_entry for this name, or
212        null if no entry was found.
213            
214 *******************************************************************************/
215
216 static classcache_name_entry *classcache_lookup_name(utf *name)
217 {
218         classcache_name_entry *c;           /* hash table element                 */
219         u4 key;                             /* hashkey computed from classname    */
220         u4 slot;                            /* slot in hashtable                  */
221 /*      u4 i; */
222
223         key  = utf_hashkey(name->text, (u4) name->blength);
224         slot = key & (hashtable_classcache.size - 1);
225         c    = hashtable_classcache.ptr[slot];
226
227         /* search external hash chain for the entry */
228
229         while (c) {
230                 /* entry found in hashtable */
231
232                 if (c->name == name)
233                         return c;
234
235                 c = c->hashlink;                    /* next element in external chain */
236         }
237
238         /* not found */
239
240         return NULL;
241 }
242
243
244 /* classcache_new_name *********************************************************
245  
246    Return a classcache_name_entry for the given name. The entry is created
247    if it is not already in the cache.
248    (internally used helper function)
249    
250    IN:
251        name.............the name to look up / create an entry for
252   
253    RETURN VALUE:
254        a pointer to the classcache_name_entry for this name
255            
256 *******************************************************************************/
257
258 static classcache_name_entry *classcache_new_name(utf *name)
259 {
260         classcache_name_entry *c;       /* hash table element */
261         u4 key;                                         /* hashkey computed from classname */
262         u4 slot;                                        /* slot in hashtable               */
263         u4 i;
264
265         key  = utf_hashkey(name->text, (u4) name->blength);
266         slot = key & (hashtable_classcache.size - 1);
267         c    = hashtable_classcache.ptr[slot];
268
269         /* search external hash chain for the entry */
270
271         while (c) {
272                 /* entry found in hashtable */
273
274                 if (c->name == name)
275                         return c;
276
277                 c = c->hashlink;                    /* next element in external chain */
278         }
279
280         /* location in hashtable found, create new entry */
281
282         c = NEW(classcache_name_entry);
283
284         c->name = name;
285         c->classes = NULL;
286
287         /* insert entry into hashtable */
288         c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
289         hashtable_classcache.ptr[slot] = c;
290
291         /* update number of hashtable-entries */
292         hashtable_classcache.entries++;
293
294         if (hashtable_classcache.entries > (hashtable_classcache.size * 2)) {
295
296                 /* reorganization of hashtable, average length of 
297                    the external chains is approx. 2                */
298
299                 classcache_name_entry *c2;
300                 hashtable newhash;              /* the new hashtable */
301
302                 /* create new hashtable, double the size */
303
304                 hashtable_create(&newhash, hashtable_classcache.size * 2);
305                 newhash.entries = hashtable_classcache.entries;
306
307                 /* transfer elements to new hashtable */
308
309                 for (i = 0; i < hashtable_classcache.size; i++) {
310                         c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
311                         while (c2) {
312                                 classcache_name_entry *nextc = c2->hashlink;
313                                 u4 newslot =
314                                         (utf_hashkey(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
315
316                                 c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
317                                 newhash.ptr[newslot] = c2;
318
319                                 c2 = nextc;
320                         }
321                 }
322
323                 /* dispose old table */
324
325                 MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
326                 hashtable_classcache = newhash;
327         }
328
329         return c;
330 }
331
332
333 /* classcache_lookup ***********************************************************
334  
335    Lookup a possibly loaded class
336   
337    IN:
338        initloader.......initiating loader for resolving the class name
339        classname........class name to look up
340   
341    RETURN VALUE:
342        The return value is a pointer to the cached class object,
343        or NULL, if the class is not in the cache.
344
345    Note: synchronized with global tablelock
346    
347 *******************************************************************************/
348
349 classinfo *classcache_lookup(classloader *initloader, utf *classname)
350 {
351         classcache_name_entry *en;
352         classcache_class_entry *clsen;
353         classcache_loader_entry *lden;
354         classinfo *cls = NULL;
355
356         CLASSCACHE_LOCK();
357
358         en = classcache_lookup_name(classname);
359
360         if (en) {
361                 /* iterate over all class entries */
362
363                 for (clsen = en->classes; clsen; clsen = clsen->next) {
364                         /* check if this entry has been loaded by initloader */
365
366                         for (lden = clsen->loaders; lden; lden = lden->next) {
367                                 if (lden->loader == initloader) {
368                                         /* found the loaded class entry */
369
370                                         assert(clsen->classobj);
371                                         cls = clsen->classobj;
372                                         goto found;
373                                 }
374                         }
375                 }
376         }
377
378   found:
379         CLASSCACHE_UNLOCK();
380         return cls;
381 }
382
383
384 /* classcache_lookup_defined ***************************************************
385  
386    Lookup a class with the given name and defining loader
387   
388    IN:
389        defloader........defining loader
390        classname........class name
391   
392    RETURN VALUE:
393        The return value is a pointer to the cached class object,
394        or NULL, if the class is not in the cache.
395    
396 *******************************************************************************/
397
398 classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
399 {
400         classcache_name_entry *en;
401         classcache_class_entry *clsen;
402         classinfo *cls = NULL;
403
404         CLASSCACHE_LOCK();
405
406         en = classcache_lookup_name(classname);
407
408         if (en) {
409                 /* iterate over all class entries */
410                 for (clsen = en->classes; clsen; clsen = clsen->next) {
411                         if (!clsen->classobj)
412                                 continue;
413
414                         /* check if this entry has been defined by defloader */
415                         if (clsen->classobj->classloader == defloader) {
416                                 cls = clsen->classobj;
417                                 goto found;
418                         }
419                 }
420         }
421
422   found:
423         CLASSCACHE_UNLOCK();
424         return cls;
425 }
426
427
428 /* classcache_lookup_defined_or_initiated **************************************
429  
430    Lookup a class that has been defined or initiated by the given loader
431   
432    IN:
433        loader...........defining or initiating loader
434        classname........class name to look up
435   
436    RETURN VALUE:
437        The return value is a pointer to the cached class object,
438        or NULL, if the class is not in the cache.
439
440    Note: synchronized with global tablelock
441    
442 *******************************************************************************/
443
444 classinfo *classcache_lookup_defined_or_initiated(classloader *loader, 
445                                                                                                   utf *classname)
446 {
447         classcache_name_entry *en;
448         classcache_class_entry *clsen;
449         classcache_loader_entry *lden;
450         classinfo *cls = NULL;
451
452         CLASSCACHE_LOCK();
453
454         en = classcache_lookup_name(classname);
455
456         if (en) {
457                 /* iterate over all class entries */
458
459                 for (clsen = en->classes; clsen; clsen = clsen->next) {
460
461                         /* check if this entry has been defined by loader */
462                         if (clsen->classobj && clsen->classobj->classloader == loader) {
463                                 cls = clsen->classobj;
464                                 goto found;
465                         }
466                         
467                         /* check if this entry has been initiated by loader */
468                         for (lden = clsen->loaders; lden; lden = lden->next) {
469                                 if (lden->loader == loader) {
470                                         /* found the loaded class entry */
471
472                                         assert(clsen->classobj);
473                                         cls = clsen->classobj;
474                                         goto found;
475                                 }
476                         }
477                 }
478         }
479
480   found:
481         CLASSCACHE_UNLOCK();
482         return cls;
483 }
484
485
486 /* classcache_store ************************************************************
487    
488    Store a loaded class. If a class of the same name has already been stored
489    with the same initiating loader, then the given class CLS is freed (if
490    possible) and the previously stored class is returned.
491   
492    IN:
493        initloader.......initiating loader used to load the class
494                             (may be NULL indicating the bootstrap loader)
495        cls..............class object to cache
496            mayfree..........true if CLS may be freed in case another class is
497                             returned
498   
499    RETURN VALUE:
500        cls..............everything ok, the class was stored in the cache,
501            other classinfo..another class with the same (initloader,name) has been
502                             stored earlier. CLS has been freed and the earlier
503                                                 stored class is returned.
504        NULL.............an exception has been thrown.
505    
506    Note: synchronized with global tablelock
507    
508 *******************************************************************************/
509
510 classinfo * classcache_store(classloader * initloader,
511                                                          classinfo * cls,
512                                                          bool mayfree)
513 {
514         classcache_name_entry *en;
515         classcache_class_entry *clsen;
516         classcache_loader_entry *lden;
517 #ifdef CLASSCACHE_VERBOSE
518         char logbuffer[1024];
519 #endif
520         
521         assert(cls);
522         assert(cls->loaded != 0);
523
524         CLASSCACHE_LOCK();
525
526 #ifdef CLASSCACHE_VERBOSE
527         sprintf(logbuffer,"classcache_store (%p,%d,", (void*)initloader,mayfree);
528         utf_strcat(logbuffer, cls->name);
529         strcat(logbuffer,")");
530         log_text(logbuffer);
531 #endif
532
533         en = classcache_new_name(cls->name);
534
535         assert(en);
536
537         /* iterate over all class entries */
538         for (clsen = en->classes; clsen; clsen = clsen->next) {
539
540                 /* check if this entry has already been loaded by initloader */
541                 for (lden = clsen->loaders; lden; lden = lden->next) {
542                         if (lden->loader == initloader && clsen->classobj != cls) {
543                                 /* A class with the same (initloader,name) pair has been stored already. */
544                                 /* We free the given class and return the earlier one.                   */
545 #ifdef CLASSCACHE_VERBOSE
546                                 dolog("replacing %p with earlier loaded class %p",cls,clsen->classobj);
547 #endif
548                                 assert(clsen->classobj);
549                                 if (mayfree)
550                                         class_free(cls);
551                                 cls = clsen->classobj;
552                                 goto return_success;
553                         }
554                 }
555
556                 /* check if initloader is constrained to this entry */
557                 for (lden = clsen->constraints; lden; lden = lden->next) {
558                         if (lden->loader == initloader) {
559                                 /* we have to use this entry */
560                                 /* check if is has already been resolved to another class */
561                                 if (clsen->classobj && clsen->classobj != cls) {
562                                         /* a loading constraint is violated */
563                                         *exceptionptr = exceptions_new_linkageerror(
564                                                                                 "loading constraint violated: ",cls);
565                                         goto return_exception;
566                                 }
567
568                                 /* record initloader as initiating loader */
569                                 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
570
571                                 /* record the loaded class object */
572                                 clsen->classobj = cls;
573
574                                 /* done */
575                                 goto return_success;
576                         }
577                 }
578
579         }
580
581         /* create a new class entry for this class object with */
582         /* initiating loader initloader                        */
583
584         clsen = NEW(classcache_class_entry);
585         clsen->classobj = cls;
586         clsen->loaders = classcache_new_loader_entry(initloader, NULL);
587         clsen->constraints = NULL;
588
589         clsen->next = en->classes;
590         en->classes = clsen;
591
592   return_success:
593         CLASSCACHE_UNLOCK();
594         return cls;
595
596   return_exception:
597         CLASSCACHE_UNLOCK();
598         return NULL;                            /* exception */
599 }
600
601 /* classcache_store_unique *****************************************************
602    
603    Store a loaded class as loaded by the bootstrap loader. This is a wrapper 
604    aroung classcache_store that throws an exception if a class with the same 
605    name has already been loaded by the bootstrap loader.
606
607    This function is used to register a few special classes during startup.
608    It should not be used otherwise.
609   
610    IN:
611        cls..............class object to cache
612   
613    RETURN VALUE:
614        true.............everything ok, the class was stored.
615        false............an exception has been thrown.
616    
617    Note: synchronized with global tablelock
618    
619 *******************************************************************************/
620
621 bool classcache_store_unique(classinfo *cls)
622 {
623         classinfo *result;
624
625         result = classcache_store(NULL,cls,false);
626         if (result == NULL)
627                 return false;
628
629         if (result != cls) {
630                 *exceptionptr = new_internalerror("class already stored in the class cache");
631                 return false;
632         }
633
634         return true;
635 }
636
637 /* classcache_store_defined ****************************************************
638    
639    Store a loaded class after it has been defined. If the class has already
640    been defined by the same defining loader in another thread, free the given
641    class and returned the one which has been defined earlier.
642   
643    IN:
644        cls..............class object to store. classloader must be set
645                             (classloader may be NULL, for bootloader)
646   
647    RETURN VALUE:
648        cls..............everything ok, the class was stored the cache,
649            other classinfo..the class had already been defined, CLS was freed, the
650                             class which was defined earlier is returned,
651        NULL.............an exception has been thrown.
652    
653 *******************************************************************************/
654
655 classinfo * classcache_store_defined(classinfo *cls)
656 {
657         classcache_name_entry *en;
658         classcache_class_entry *clsen;
659 #ifdef CLASSCACHE_VERBOSE
660         char logbuffer[1024];
661 #endif
662
663         assert(cls);
664         assert(cls->loaded != 0);
665
666         CLASSCACHE_LOCK();
667
668 #ifdef CLASSCACHE_VERBOSE
669         sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
670         utf_strcat(logbuffer, cls->name);
671         strcat(logbuffer,")");
672         log_text(logbuffer);
673 #endif
674
675         en = classcache_new_name(cls->name);
676
677         assert(en);
678
679         /* iterate over all class entries */
680         for (clsen = en->classes; clsen; clsen = clsen->next) {
681                 
682                 /* check if this class has been defined by the same classloader */
683                 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
684                         /* we found an earlier definition, delete the newer one */
685                         /* (if it is a different classinfo)                     */
686                         if (clsen->classobj != cls) {
687 #ifdef CLASSCACHE_VERBOSE
688                                 dolog("replacing %p with earlier defined class %p",cls,clsen->classobj);
689 #endif
690                                 class_free(cls);
691                                 cls = clsen->classobj;
692                         }
693                         goto return_success;
694                 }
695         }
696
697         /* create a new class entry for this class object */
698         /* the list of initiating loaders is empty at this point */
699
700         clsen = NEW(classcache_class_entry);
701         clsen->classobj = cls;
702         clsen->loaders = NULL;
703         clsen->constraints = NULL;
704
705         clsen->next = en->classes;
706         en->classes = clsen;
707
708 return_success:
709         CLASSCACHE_UNLOCK();
710         return cls;
711 }
712
713 /* classcache_find_loader ******************************************************
714  
715    Find the class entry loaded by or constrained to a given loader
716    (internally used helper function)
717   
718    IN:
719        entry............the classcache_name_entry
720        loader...........the loader to look for
721   
722    RETURN VALUE:
723        the classcache_class_entry for the given loader, or
724            NULL if no entry was found
725    
726 *******************************************************************************/
727
728 static classcache_class_entry * classcache_find_loader(
729                                                                         classcache_name_entry * entry,
730                                                                         classloader * loader)
731 {
732         classcache_class_entry *clsen;
733         classcache_loader_entry *lden;
734
735         assert(entry);
736
737         /* iterate over all class entries */
738         for (clsen = entry->classes; clsen; clsen = clsen->next) {
739
740                 /* check if this entry has already been loaded by initloader */
741                 for (lden = clsen->loaders; lden; lden = lden->next) {
742                         if (lden->loader == loader)
743                                 return clsen;   /* found */
744                 }
745
746                 /* check if loader is constrained to this entry */
747                 for (lden = clsen->constraints; lden; lden = lden->next) {
748                         if (lden->loader == loader)
749                                 return clsen;   /* found */
750                 }
751         }
752
753         /* not found */
754         return NULL;
755 }
756
757 /* classcache_free_class_entry *************************************************
758  
759    Free the memory used by a class entry
760   
761    IN:
762        clsen............the classcache_class_entry to free  
763            
764 *******************************************************************************/
765
766 static void classcache_free_class_entry(classcache_class_entry * clsen)
767 {
768         classcache_loader_entry *lden;
769         classcache_loader_entry *next;
770
771         assert(clsen);
772
773         for (lden = clsen->loaders; lden; lden = next) {
774                 next = lden->next;
775                 FREE(lden, classcache_loader_entry);
776         }
777         for (lden = clsen->constraints; lden; lden = next) {
778                 next = lden->next;
779                 FREE(lden, classcache_loader_entry);
780         }
781
782         FREE(clsen, classcache_class_entry);
783 }
784
785 /* classcache_remove_class_entry ***********************************************
786  
787    Remove a classcache_class_entry from the list of possible resolution of
788    a name entry
789    (internally used helper function)
790   
791    IN:
792        entry............the classcache_name_entry
793        clsen............the classcache_class_entry to remove
794   
795 *******************************************************************************/
796
797 static void classcache_remove_class_entry(classcache_name_entry * entry,
798                                                                                   classcache_class_entry * clsen)
799 {
800         classcache_class_entry **chain;
801
802         assert(entry);
803         assert(clsen);
804
805         chain = &(entry->classes);
806         while (*chain) {
807                 if (*chain == clsen) {
808                         *chain = clsen->next;
809                         classcache_free_class_entry(clsen);
810                         return;
811                 }
812                 chain = &((*chain)->next);
813         }
814 }
815
816 /* classcache_free_name_entry **************************************************
817  
818    Free the memory used by a name entry
819   
820    IN:
821        entry............the classcache_name_entry to free  
822            
823 *******************************************************************************/
824
825 static void classcache_free_name_entry(classcache_name_entry * entry)
826 {
827         classcache_class_entry *clsen;
828         classcache_class_entry *next;
829
830         assert(entry);
831
832         for (clsen = entry->classes; clsen; clsen = next) {
833                 next = clsen->next;
834                 classcache_free_class_entry(clsen);
835         }
836
837         FREE(entry, classcache_name_entry);
838 }
839
840 /* classcache_free *************************************************************
841  
842    Free the memory used by the class cache
843
844    NOTE:
845        The class cache may not be used any more after this call, except
846            when it is reinitialized with classcache_init.
847   
848    Note: NOT synchronized!
849   
850 *******************************************************************************/
851
852 void classcache_free(void)
853 {
854         u4 slot;
855         classcache_name_entry *entry;
856         classcache_name_entry *next;
857
858         for (slot = 0; slot < hashtable_classcache.size; ++slot) {
859                 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
860                         next = entry->hashlink;
861                         classcache_free_name_entry(entry);
862                 }
863         }
864
865         MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
866         hashtable_classcache.size = 0;
867         hashtable_classcache.entries = 0;
868         hashtable_classcache.ptr = NULL;
869 }
870
871 /* classcache_add_constraint ***************************************************
872  
873    Add a loading constraint
874   
875    IN:
876        a................first initiating loader
877        b................second initiating loader
878        classname........class name
879   
880    RETURN VALUE:
881        true.............everything ok, the constraint has been added,
882        false............an exception has been thrown.
883    
884    Note: synchronized with global tablelock
885    
886 *******************************************************************************/
887
888 bool classcache_add_constraint(classloader * a,
889                                                            classloader * b,
890                                                            utf * classname)
891 {
892         classcache_name_entry *en;
893         classcache_class_entry *clsenA;
894         classcache_class_entry *clsenB;
895
896         assert(classname);
897
898 #ifdef CLASSCACHE_VERBOSE
899         fprintf(stderr, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
900         utf_fprint_classname(stderr, classname);
901         fprintf(stderr, ")\n");
902 #endif
903
904         /* a constraint with a == b is trivially satisfied */
905         if (a == b)
906                 return true;
907
908         CLASSCACHE_LOCK();
909
910         en = classcache_new_name(classname);
911
912         assert(en);
913
914         /* find the entry loaded by / constrained to each loader */
915         clsenA = classcache_find_loader(en, a);
916         clsenB = classcache_find_loader(en, b);
917
918         if (clsenA && clsenB) {
919                 /* { both loaders have corresponding entries } */
920
921                 /* if the entries are the same, the constraint is already recorded */
922                 if (clsenA == clsenB)
923                         goto return_success;
924
925                 /* check if the entries can be merged */
926                 if (clsenA->classobj && clsenB->classobj
927                         && clsenA->classobj != clsenB->classobj) {
928                         /* no, the constraint is violated */
929                         *exceptionptr = exceptions_new_linkageerror(
930                                                           "loading constraint violated: ",clsenA->classobj);
931                         goto return_exception;
932                 }
933
934                 /* yes, merge the entries */
935                 /* clsenB will be merged into clsenA */
936                 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
937                 clsenB->loaders = NULL;
938
939                 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
940                                                                                                            clsenB->constraints);
941                 clsenB->constraints = NULL;
942
943                 if (!clsenA->classobj)
944                         clsenA->classobj = clsenB->classobj;
945
946                 /* remove clsenB from the list of class entries */
947                 classcache_remove_class_entry(en, clsenB);
948         }
949         else {
950                 /* { at most one of the loaders has a corresponding entry } */
951
952                 /* set clsenA to the single class entry we have */
953                 if (!clsenA)
954                         clsenA = clsenB;
955
956                 if (!clsenA) {
957                         /* { no loader has a corresponding entry } */
958
959                         /* create a new class entry with the constraint (a,b,en->name) */
960                         clsenA = NEW(classcache_class_entry);
961                         clsenA->classobj = NULL;
962                         clsenA->loaders = NULL;
963                         clsenA->constraints = classcache_new_loader_entry(b, NULL);
964                         clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
965
966                         clsenA->next = en->classes;
967                         en->classes = clsenA;
968                 }
969                 else {
970                         /* make b the loader that has no corresponding entry */
971                         if (clsenB)
972                                 b = a;
973
974                         /* loader b must be added to entry clsenA */
975                         clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
976                 }
977         }
978
979   return_success:
980         CLASSCACHE_UNLOCK();
981         return true;
982
983   return_exception:
984         CLASSCACHE_UNLOCK();
985         return false;                           /* exception */
986 }
987
988 /*============================================================================*/
989 /* DEBUG DUMPS                                                                */
990 /*============================================================================*/
991
992 /* classcache_debug_dump *******************************************************
993  
994    Print the contents of the loaded class cache to a stream
995   
996    IN:
997        file.............output stream
998   
999    Note: synchronized with global tablelock
1000    
1001 *******************************************************************************/
1002
1003 #ifndef NDEBUG
1004 void classcache_debug_dump(FILE * file)
1005 {
1006         classcache_name_entry *c;
1007         classcache_class_entry *clsen;
1008         classcache_loader_entry *lden;
1009         u4 slot;
1010
1011         CLASSCACHE_LOCK();
1012
1013         fprintf(file, "\n=== [loaded class cache] =====================================\n\n");
1014         fprintf(file, "hash size   : %d\n", (int) hashtable_classcache.size);
1015         fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries);
1016         fprintf(file, "\n");
1017
1018         for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1019                 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1020
1021                 for (; c; c = c->hashlink) {
1022                         utf_fprint_classname(file, c->name);
1023                         fprintf(file, "\n");
1024
1025                         /* iterate over all class entries */
1026                         for (clsen = c->classes; clsen; clsen = clsen->next) {
1027                                 if (clsen->classobj) {
1028                                         fprintf(file, "    loaded %p\n", (void *) clsen->classobj);
1029                                 }
1030                                 else {
1031                                         fprintf(file, "    unresolved\n");
1032                                 }
1033                                 fprintf(file, "        loaders:");
1034                                 for (lden = clsen->loaders; lden; lden = lden->next) {
1035                                         fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1036                                 }
1037                                 fprintf(file, "\n        constraints:");
1038                                 for (lden = clsen->constraints; lden; lden = lden->next) {
1039                                         fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1040                                 }
1041                                 fprintf(file, "\n");
1042                         }
1043                 }
1044         }
1045         fprintf(file, "\n==============================================================\n\n");
1046
1047         CLASSCACHE_UNLOCK();
1048 }
1049 #endif /* NDEBUG */
1050
1051 /*
1052  * These are local overrides for various environment variables in Emacs.
1053  * Please do not remove this and leave it at the end of the file, where
1054  * Emacs will automagically detect them.
1055  * ---------------------------------------------------------------------
1056  * Local variables:
1057  * mode: c
1058  * indent-tabs-mode: t
1059  * c-basic-offset: 4
1060  * tab-width: 4
1061  * End:
1062  * vim:noexpandtab:sw=4:ts=4:
1063  */