LCOV - code coverage report
Current view: top level - vm - classcache.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 209 345 60.6 %
Date: 2015-06-10 18:10:59 Functions: 16 23 69.6 %

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

Generated by: LCOV version 1.11