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