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