* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / classcache.c
1 /* src/vm/classcache.c - loaded class cache and loading constraints
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Edwin Steiner
28
29    Changes: Christian Thalinger
30
31    $Id: classcache.c 4357 2006-01-22 23:33:38Z 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, classinfo *cls,
511                                                         bool mayfree)
512 {
513         classcache_name_entry *en;
514         classcache_class_entry *clsen;
515         classcache_loader_entry *lden;
516 #ifdef CLASSCACHE_VERBOSE
517         char logbuffer[1024];
518 #endif
519         
520         assert(cls);
521         assert(cls->state & CLASS_LOADED);
522
523         CLASSCACHE_LOCK();
524
525 #ifdef CLASSCACHE_VERBOSE
526         sprintf(logbuffer,"classcache_store (%p,%d,", (void*)initloader,mayfree);
527         utf_strcat(logbuffer, cls->name);
528         strcat(logbuffer,")");
529         log_text(logbuffer);
530 #endif
531
532         en = classcache_new_name(cls->name);
533
534         assert(en);
535
536         /* iterate over all class entries */
537         for (clsen = en->classes; clsen; clsen = clsen->next) {
538
539                 /* check if this entry has already been loaded by initloader */
540                 for (lden = clsen->loaders; lden; lden = lden->next) {
541                         if (lden->loader == initloader && clsen->classobj != cls) {
542                                 /* A class with the same (initloader,name) pair has been stored already. */
543                                 /* We free the given class and return the earlier one.                   */
544 #ifdef CLASSCACHE_VERBOSE
545                                 dolog("replacing %p with earlier loaded class %p",cls,clsen->classobj);
546 #endif
547                                 assert(clsen->classobj);
548                                 if (mayfree)
549                                         class_free(cls);
550                                 cls = clsen->classobj;
551                                 goto return_success;
552                         }
553                 }
554
555                 /* check if initloader is constrained to this entry */
556                 for (lden = clsen->constraints; lden; lden = lden->next) {
557                         if (lden->loader == initloader) {
558                                 /* we have to use this entry */
559                                 /* check if is has already been resolved to another class */
560                                 if (clsen->classobj && clsen->classobj != cls) {
561                                         /* a loading constraint is violated */
562                                         *exceptionptr = exceptions_new_linkageerror(
563                                                                                 "loading constraint violated: ",cls);
564                                         goto return_exception;
565                                 }
566
567                                 /* record initloader as initiating loader */
568                                 clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
569
570                                 /* record the loaded class object */
571                                 clsen->classobj = cls;
572
573                                 /* done */
574                                 goto return_success;
575                         }
576                 }
577
578         }
579
580         /* create a new class entry for this class object with */
581         /* initiating loader initloader                        */
582
583         clsen = NEW(classcache_class_entry);
584         clsen->classobj = cls;
585         clsen->loaders = classcache_new_loader_entry(initloader, NULL);
586         clsen->constraints = NULL;
587
588         clsen->next = en->classes;
589         en->classes = clsen;
590
591   return_success:
592         CLASSCACHE_UNLOCK();
593         return cls;
594
595   return_exception:
596         CLASSCACHE_UNLOCK();
597         return NULL;                            /* exception */
598 }
599
600 /* classcache_store_unique *****************************************************
601    
602    Store a loaded class as loaded by the bootstrap loader. This is a wrapper 
603    aroung classcache_store that throws an exception if a class with the same 
604    name has already been loaded by the bootstrap loader.
605
606    This function is used to register a few special classes during startup.
607    It should not be used otherwise.
608   
609    IN:
610        cls..............class object to cache
611   
612    RETURN VALUE:
613        true.............everything ok, the class was stored.
614        false............an exception has been thrown.
615    
616    Note: synchronized with global tablelock
617    
618 *******************************************************************************/
619
620 bool classcache_store_unique(classinfo *cls)
621 {
622         classinfo *result;
623
624         result = classcache_store(NULL,cls,false);
625         if (result == NULL)
626                 return false;
627
628         if (result != cls) {
629                 *exceptionptr = new_internalerror("class already stored in the class cache");
630                 return false;
631         }
632
633         return true;
634 }
635
636 /* classcache_store_defined ****************************************************
637    
638    Store a loaded class after it has been defined. If the class has already
639    been defined by the same defining loader in another thread, free the given
640    class and returned the one which has been defined earlier.
641   
642    IN:
643        cls..............class object to store. classloader must be set
644                             (classloader may be NULL, for bootloader)
645   
646    RETURN VALUE:
647        cls..............everything ok, the class was stored the cache,
648            other classinfo..the class had already been defined, CLS was freed, the
649                             class which was defined earlier is returned,
650        NULL.............an exception has been thrown.
651    
652 *******************************************************************************/
653
654 classinfo *classcache_store_defined(classinfo *cls)
655 {
656         classcache_name_entry *en;
657         classcache_class_entry *clsen;
658 #ifdef CLASSCACHE_VERBOSE
659         char logbuffer[1024];
660 #endif
661
662         assert(cls);
663         assert(cls->state & CLASS_LOADED);
664
665         CLASSCACHE_LOCK();
666
667 #ifdef CLASSCACHE_VERBOSE
668         sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
669         utf_strcat(logbuffer, cls->name);
670         strcat(logbuffer,")");
671         log_text(logbuffer);
672 #endif
673
674         en = classcache_new_name(cls->name);
675
676         assert(en);
677
678         /* iterate over all class entries */
679         for (clsen = en->classes; clsen; clsen = clsen->next) {
680                 
681                 /* check if this class has been defined by the same classloader */
682                 if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
683                         /* we found an earlier definition, delete the newer one */
684                         /* (if it is a different classinfo)                     */
685                         if (clsen->classobj != cls) {
686 #ifdef CLASSCACHE_VERBOSE
687                                 dolog("replacing %p with earlier defined class %p",cls,clsen->classobj);
688 #endif
689                                 class_free(cls);
690                                 cls = clsen->classobj;
691                         }
692                         goto return_success;
693                 }
694         }
695
696         /* create a new class entry for this class object */
697         /* the list of initiating loaders is empty at this point */
698
699         clsen = NEW(classcache_class_entry);
700         clsen->classobj = cls;
701         clsen->loaders = NULL;
702         clsen->constraints = NULL;
703
704         clsen->next = en->classes;
705         en->classes = clsen;
706
707 return_success:
708         CLASSCACHE_UNLOCK();
709         return cls;
710 }
711
712 /* classcache_find_loader ******************************************************
713  
714    Find the class entry loaded by or constrained to a given loader
715    (internally used helper function)
716   
717    IN:
718        entry............the classcache_name_entry
719        loader...........the loader to look for
720   
721    RETURN VALUE:
722        the classcache_class_entry for the given loader, or
723            NULL if no entry was found
724    
725 *******************************************************************************/
726
727 static classcache_class_entry * classcache_find_loader(
728                                                                         classcache_name_entry * entry,
729                                                                         classloader * loader)
730 {
731         classcache_class_entry *clsen;
732         classcache_loader_entry *lden;
733
734         assert(entry);
735
736         /* iterate over all class entries */
737         for (clsen = entry->classes; clsen; clsen = clsen->next) {
738
739                 /* check if this entry has already been loaded by initloader */
740                 for (lden = clsen->loaders; lden; lden = lden->next) {
741                         if (lden->loader == loader)
742                                 return clsen;   /* found */
743                 }
744
745                 /* check if loader is constrained to this entry */
746                 for (lden = clsen->constraints; lden; lden = lden->next) {
747                         if (lden->loader == loader)
748                                 return clsen;   /* found */
749                 }
750         }
751
752         /* not found */
753         return NULL;
754 }
755
756 /* classcache_free_class_entry *************************************************
757  
758    Free the memory used by a class entry
759   
760    IN:
761        clsen............the classcache_class_entry to free  
762            
763 *******************************************************************************/
764
765 static void classcache_free_class_entry(classcache_class_entry * clsen)
766 {
767         classcache_loader_entry *lden;
768         classcache_loader_entry *next;
769
770         assert(clsen);
771
772         for (lden = clsen->loaders; lden; lden = next) {
773                 next = lden->next;
774                 FREE(lden, classcache_loader_entry);
775         }
776         for (lden = clsen->constraints; lden; lden = next) {
777                 next = lden->next;
778                 FREE(lden, classcache_loader_entry);
779         }
780
781         FREE(clsen, classcache_class_entry);
782 }
783
784 /* classcache_remove_class_entry ***********************************************
785  
786    Remove a classcache_class_entry from the list of possible resolution of
787    a name entry
788    (internally used helper function)
789   
790    IN:
791        entry............the classcache_name_entry
792        clsen............the classcache_class_entry to remove
793   
794 *******************************************************************************/
795
796 static void classcache_remove_class_entry(classcache_name_entry * entry,
797                                                                                   classcache_class_entry * clsen)
798 {
799         classcache_class_entry **chain;
800
801         assert(entry);
802         assert(clsen);
803
804         chain = &(entry->classes);
805         while (*chain) {
806                 if (*chain == clsen) {
807                         *chain = clsen->next;
808                         classcache_free_class_entry(clsen);
809                         return;
810                 }
811                 chain = &((*chain)->next);
812         }
813 }
814
815 /* classcache_free_name_entry **************************************************
816  
817    Free the memory used by a name entry
818   
819    IN:
820        entry............the classcache_name_entry to free  
821            
822 *******************************************************************************/
823
824 static void classcache_free_name_entry(classcache_name_entry * entry)
825 {
826         classcache_class_entry *clsen;
827         classcache_class_entry *next;
828
829         assert(entry);
830
831         for (clsen = entry->classes; clsen; clsen = next) {
832                 next = clsen->next;
833                 classcache_free_class_entry(clsen);
834         }
835
836         FREE(entry, classcache_name_entry);
837 }
838
839 /* classcache_free *************************************************************
840  
841    Free the memory used by the class cache
842
843    NOTE:
844        The class cache may not be used any more after this call, except
845            when it is reinitialized with classcache_init.
846   
847    Note: NOT synchronized!
848   
849 *******************************************************************************/
850
851 void classcache_free(void)
852 {
853         u4 slot;
854         classcache_name_entry *entry;
855         classcache_name_entry *next;
856
857         for (slot = 0; slot < hashtable_classcache.size; ++slot) {
858                 for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
859                         next = entry->hashlink;
860                         classcache_free_name_entry(entry);
861                 }
862         }
863
864         MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
865         hashtable_classcache.size = 0;
866         hashtable_classcache.entries = 0;
867         hashtable_classcache.ptr = NULL;
868 }
869
870 /* classcache_add_constraint ***************************************************
871  
872    Add a loading constraint
873   
874    IN:
875        a................first initiating loader
876        b................second initiating loader
877        classname........class name
878   
879    RETURN VALUE:
880        true.............everything ok, the constraint has been added,
881        false............an exception has been thrown.
882    
883    Note: synchronized with global tablelock
884    
885 *******************************************************************************/
886
887 bool classcache_add_constraint(classloader * a,
888                                                            classloader * b,
889                                                            utf * classname)
890 {
891         classcache_name_entry *en;
892         classcache_class_entry *clsenA;
893         classcache_class_entry *clsenB;
894
895         assert(classname);
896
897 #ifdef CLASSCACHE_VERBOSE
898         fprintf(stderr, "classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
899         utf_fprint_classname(stderr, classname);
900         fprintf(stderr, ")\n");
901 #endif
902
903         /* a constraint with a == b is trivially satisfied */
904         if (a == b)
905                 return true;
906
907         CLASSCACHE_LOCK();
908
909         en = classcache_new_name(classname);
910
911         assert(en);
912
913         /* find the entry loaded by / constrained to each loader */
914         clsenA = classcache_find_loader(en, a);
915         clsenB = classcache_find_loader(en, b);
916
917         if (clsenA && clsenB) {
918                 /* { both loaders have corresponding entries } */
919
920                 /* if the entries are the same, the constraint is already recorded */
921                 if (clsenA == clsenB)
922                         goto return_success;
923
924                 /* check if the entries can be merged */
925                 if (clsenA->classobj && clsenB->classobj
926                         && clsenA->classobj != clsenB->classobj) {
927                         /* no, the constraint is violated */
928                         *exceptionptr = exceptions_new_linkageerror(
929                                                           "loading constraint violated: ",clsenA->classobj);
930                         goto return_exception;
931                 }
932
933                 /* yes, merge the entries */
934                 /* clsenB will be merged into clsenA */
935                 clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
936                 clsenB->loaders = NULL;
937
938                 clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
939                                                                                                            clsenB->constraints);
940                 clsenB->constraints = NULL;
941
942                 if (!clsenA->classobj)
943                         clsenA->classobj = clsenB->classobj;
944
945                 /* remove clsenB from the list of class entries */
946                 classcache_remove_class_entry(en, clsenB);
947         }
948         else {
949                 /* { at most one of the loaders has a corresponding entry } */
950
951                 /* set clsenA to the single class entry we have */
952                 if (!clsenA)
953                         clsenA = clsenB;
954
955                 if (!clsenA) {
956                         /* { no loader has a corresponding entry } */
957
958                         /* create a new class entry with the constraint (a,b,en->name) */
959                         clsenA = NEW(classcache_class_entry);
960                         clsenA->classobj = NULL;
961                         clsenA->loaders = NULL;
962                         clsenA->constraints = classcache_new_loader_entry(b, NULL);
963                         clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
964
965                         clsenA->next = en->classes;
966                         en->classes = clsenA;
967                 }
968                 else {
969                         /* make b the loader that has no corresponding entry */
970                         if (clsenB)
971                                 b = a;
972
973                         /* loader b must be added to entry clsenA */
974                         clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
975                 }
976         }
977
978   return_success:
979         CLASSCACHE_UNLOCK();
980         return true;
981
982   return_exception:
983         CLASSCACHE_UNLOCK();
984         return false;                           /* exception */
985 }
986
987 /*============================================================================*/
988 /* DEBUG DUMPS                                                                */
989 /*============================================================================*/
990
991 /* classcache_debug_dump *******************************************************
992  
993    Print the contents of the loaded class cache to a stream
994   
995    IN:
996        file.............output stream
997   
998    Note: synchronized with global tablelock
999    
1000 *******************************************************************************/
1001
1002 #ifndef NDEBUG
1003 void classcache_debug_dump(FILE * file)
1004 {
1005         classcache_name_entry *c;
1006         classcache_class_entry *clsen;
1007         classcache_loader_entry *lden;
1008         u4 slot;
1009
1010         CLASSCACHE_LOCK();
1011
1012         fprintf(file, "\n=== [loaded class cache] =====================================\n\n");
1013         fprintf(file, "hash size   : %d\n", (int) hashtable_classcache.size);
1014         fprintf(file, "hash entries: %d\n", (int) hashtable_classcache.entries);
1015         fprintf(file, "\n");
1016
1017         for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1018                 c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1019
1020                 for (; c; c = c->hashlink) {
1021                         utf_fprint_classname(file, c->name);
1022                         fprintf(file, "\n");
1023
1024                         /* iterate over all class entries */
1025                         for (clsen = c->classes; clsen; clsen = clsen->next) {
1026                                 if (clsen->classobj) {
1027                                         fprintf(file, "    loaded %p\n", (void *) clsen->classobj);
1028                                 }
1029                                 else {
1030                                         fprintf(file, "    unresolved\n");
1031                                 }
1032                                 fprintf(file, "        loaders:");
1033                                 for (lden = clsen->loaders; lden; lden = lden->next) {
1034                                         fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1035                                 }
1036                                 fprintf(file, "\n        constraints:");
1037                                 for (lden = clsen->constraints; lden; lden = lden->next) {
1038                                         fprintf(file, "<%p> %p", (void *) lden, (void *) lden->loader);
1039                                 }
1040                                 fprintf(file, "\n");
1041                         }
1042                 }
1043         }
1044         fprintf(file, "\n==============================================================\n\n");
1045
1046         CLASSCACHE_UNLOCK();
1047 }
1048 #endif /* NDEBUG */
1049
1050 /*
1051  * These are local overrides for various environment variables in Emacs.
1052  * Please do not remove this and leave it at the end of the file, where
1053  * Emacs will automagically detect them.
1054  * ---------------------------------------------------------------------
1055  * Local variables:
1056  * mode: c
1057  * indent-tabs-mode: t
1058  * c-basic-offset: 4
1059  * tab-width: 4
1060  * End:
1061  * vim:noexpandtab:sw=4:ts=4:
1062  */