CACAO
classcache.cpp
Go to the documentation of this file.
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 
224 
226 
227 
228 /*============================================================================*/
229 /* */
230 /*============================================================================*/
231 
232 /* prototypes */
233 
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 bool classcache_init(void)
248 {
249  TRACESUBSYSTEMINITIALIZATION("classcache_init");
250 
251  /* create the hashtable */
252 
253  hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
254 
255  /* create utf hashtable mutex */
256 
257  classcache_hashtable_mutex = new Mutex();
258 
259  /* everything's ok */
260 
261  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 
281 {
283 
285  lden->loader = loader;
286  lden->next = next;
287  CLASSCACHE_COUNT(stat_new_loader_entry);
288 
289  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 
310  classcache_loader_entry * lista,
311  classcache_loader_entry * listb)
312 {
313  classcache_loader_entry *result;
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  result = NULL;
325  chain = &result;
326 
327  for (ldenA = lista; ldenA; ldenA = ldenA->next) {
328 
329  for (ldenB = listb; ldenB; ldenB = ldenB->next) {
330  if (ldenB->loader == ldenA->loader)
331  goto common_element;
332  }
333 
334  /* this loader is only in lista */
335  *chain = ldenA;
336  chain = &(ldenA->next);
337 
338  common_element:
339  /* XXX free the duplicated element */
340  ;
341  }
342 
343  /* concat listb to the result */
344  *chain = listb;
345 
346  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 
369  classcache_class_entry *clsenA,
370  classcache_class_entry *clsenB)
371 {
372 #ifdef CLASSCACHE_VERBOSE
373  Buffer<> logbuffer;
374 #endif
375 
376  assert(en);
377  assert(clsenA);
378  assert(clsenB);
379  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  clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
395  clsenB->loaders = NULL; /* these have been freed or reused */
396 
398  clsenB->constraints);
399  clsenB->constraints = NULL; /* these have been freed or reused */
400 
401  if (!clsenA->classobj)
402  clsenA->classobj = clsenB->classobj;
403 
404  /* remove clsenB from the list of class entries */
405  classcache_remove_class_entry(en, clsenB);
406 }
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 
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  key = name.hash();
432  slot = key & (hashtable_classcache.size - 1);
433  c = (classcache_name_entry*) hashtable_classcache.ptr[slot];
434 
435  /* search external hash chain for the entry */
436 
437  while (c) {
438  /* entry found in hashtable */
439  CLASSCACHE_COUNT(stat_lookup_name_entry);
440 
441  if (c->name == name)
442  return c;
443 
444  c = c->hashlink; /* next element in external chain */
445  }
446 
447  /* not found */
448 
449  CLASSCACHE_COUNT(stat_lookup_name_notfound);
450  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 
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  key = name.hash();
478  slot = key & (hashtable_classcache.size - 1);
479  c = (classcache_name_entry*) hashtable_classcache.ptr[slot];
480 
481  /* search external hash chain for the entry */
482 
483  while (c) {
484  /* entry found in hashtable */
485  CLASSCACHE_COUNT(stat_lookup_new_name_entry);
486 
487  if (c->name == name)
488  return c;
489 
490  c = c->hashlink; /* next element in external chain */
491  }
492 
493  /* location in hashtable found, create new entry */
494 
496 
497  c->name = name;
498  c->classes = NULL;
499 
500  /* insert entry into hashtable */
501  c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
502  CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
503  hashtable_classcache.ptr[slot] = c;
504 
505  /* update number of hashtable-entries */
506  hashtable_classcache.entries++;
507  CLASSCACHE_COUNT(stat_classnames_stored);
508 
509  if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
510  /* reorganization of hashtable */
511 
513  hashtable newhash; /* the new hashtable */
514 
515  CLASSCACHE_COUNT(stat_rehash_names);
516 
517  /* create new hashtable, double the size */
518 
519  hashtable_create(&newhash, hashtable_classcache.size * 2);
520  newhash.entries = hashtable_classcache.entries;
521 
522  /* transfer elements to new hashtable */
523 
524  for (i = 0; i < hashtable_classcache.size; i++) {
525  c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
526  while (c2) {
527  classcache_name_entry *nextc = c2->hashlink;
528  u4 newslot = c2->name.hash() & (newhash.size - 1);
529 
530  c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
531  CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
532  newhash.ptr[newslot] = c2;
533 
534  c2 = nextc;
535  }
536  }
537 
538  /* dispose old table */
539 
540  MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
541  hashtable_classcache = newhash;
542  }
543 
544  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 
565 {
567  classcache_class_entry *clsen;
569  classinfo *cls = NULL;
570 
571  CLASSCACHE_LOCK();
572 
573  CLASSCACHE_COUNT(stat_lookup);
574  en = classcache_lookup_name(classname);
575 
576  if (en) {
577  /* iterate over all class entries */
578 
579  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  for (lden = clsen->loaders; lden; lden = lden->next) {
584  CLASSCACHE_COUNT(stat_lookup_loader_checked);
585  if (lden->loader == initloader) {
586  /* found the loaded class entry */
587 
588  assert(clsen->classobj);
589  cls = clsen->classobj;
590  goto found;
591  }
592  }
593  }
594  }
595 
596  found:
598  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 
617 {
619  classcache_class_entry *clsen;
620  classinfo *cls = NULL;
621 
622  CLASSCACHE_LOCK();
623 
624  en = classcache_lookup_name(classname);
625 
626  if (en) {
627  /* iterate over all class entries */
628  for (clsen = en->classes; clsen; clsen = clsen->next) {
629  if (!clsen->classobj)
630  continue;
631 
632  /* check if this entry has been defined by defloader */
633  if (clsen->classobj->classloader == defloader) {
634  cls = clsen->classobj;
635  goto found;
636  }
637  }
638  }
639 
640  found:
642  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 
663  Utf8String classname)
664 {
666  classcache_class_entry *clsen;
668  classinfo *cls = NULL;
669 
670  CLASSCACHE_LOCK();
671 
672  en = classcache_lookup_name(classname);
673 
674  if (en) {
675  /* iterate over all class entries */
676 
677  for (clsen = en->classes; clsen; clsen = clsen->next) {
678 
679  /* check if this entry has been defined by loader */
680  if (clsen->classobj && clsen->classobj->classloader == loader) {
681  cls = clsen->classobj;
682  goto found;
683  }
684 
685  /* check if this entry has been initiated by loader */
686  for (lden = clsen->loaders; lden; lden = lden->next) {
687  if (lden->loader == loader) {
688  /* found the loaded class entry */
689 
690  assert(clsen->classobj);
691  cls = clsen->classobj;
692  goto found;
693  }
694  }
695  }
696  }
697 
698  found:
700  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 
731  bool mayfree)
732 {
734  classcache_class_entry *clsen;
735  classcache_class_entry *clsenB;
737 #ifdef CLASSCACHE_VERBOSE
738  Buffer<> logbuffer;
739 #endif
740 
741  assert(cls);
742  assert(cls->state & CLASS_LOADED);
743 
744  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  en = classcache_new_name(cls->name);
754 
755  assert(en);
756 
757  /* iterate over all class entries */
758  for (clsen = en->classes; clsen; clsen = clsen->next) {
759 
760  /* check if this entry has already been loaded by initloader */
761  for (lden = clsen->loaders; lden; lden = lden->next) {
762  if (lden->loader == initloader) {
763  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  assert(clsen->classobj);
770  if (mayfree)
771  class_free(cls);
772  cls = clsen->classobj;
773  }
774  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  for (lden = clsen->constraints; lden; lden = lden->next) {
782  if (lden->loader == initloader) {
783  /* we have to use this entry. check if it has been resolved */
784  if (clsen->classobj) {
785  /* check if is has already been resolved to another class */
786  if (clsen->classobj != cls) {
787  /* a loading constraint is violated */
788  exceptions_throw_linkageerror("loading constraint violated: ", cls);
789  goto return_exception;
790  }
791 
792  /* record initloader as initiating loader */
793  clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
794  goto return_success;
795  }
796 
797  /* {this is the first resolution for this entry} */
798  /* record initloader as initiating loader */
799  clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
800 
801  /* maybe we can merge this entry with another one */
802  for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
803  /* we dont want the entry that we have already */
804  if (clsenB->classobj == cls) {
805  /* this entry has the same classobj. let's merge them */
806  classcache_merge_class_entries(en,clsen,clsenB);
807  goto return_success;
808  }
809  }
810 
811  /* record the loaded class object */
812  clsen->classobj = cls;
813  CLASSCACHE_COUNT(stat_classes_stored);
814 
815  /* done */
816  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  for (clsen = en->classes; clsen; clsen = clsen->next) {
827  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  for (lden = clsen->loaders; lden; lden = lden->next) {
831  if (lden->loader == initloader)
832  goto return_success;
833  }
834  clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
835  goto return_success;
836  }
837  }
838 
839  /* create a new class entry for this class object with */
840  /* initiating loader initloader */
841 
842  clsen = NEW(classcache_class_entry);
843  clsen->classobj = cls;
844  clsen->loaders = classcache_new_loader_entry(initloader, NULL);
845  clsen->constraints = NULL;
846 
847  clsen->next = en->classes;
848  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
856  return cls;
857 
858  return_exception:
860  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 
884 {
885  classinfo *result;
886 
887  result = classcache_store(NULL,cls,false);
888  if (result == NULL)
889  return false;
890 
891  if (result != cls) {
892  exceptions_throw_internalerror("class already stored in the class cache");
893  return false;
894  }
895 
896  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 
918 {
920  classcache_class_entry *clsen;
921 #ifdef CLASSCACHE_VERBOSE
922  Buffer<> logbuffer;
923 #endif
924 
925  assert(cls);
926  assert(cls->state & CLASS_LOADED);
927 
928  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  en = classcache_new_name(cls->name);
938 
939  assert(en);
940 
941  /* iterate over all class entries */
942  for (clsen = en->classes; clsen; clsen = clsen->next) {
943 
944  /* check if this class has been defined by the same classloader */
945  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  if (clsen->classobj != cls) {
949 #ifdef CLASSCACHE_VERBOSE
950  log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
951 #endif
952  class_free(cls);
953  cls = clsen->classobj;
954  }
955  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  clsen = NEW(classcache_class_entry);
963  clsen->classobj = cls;
964  clsen->loaders = NULL;
965  clsen->constraints = NULL;
966 
967  clsen->next = en->classes;
968  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
976  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)
996  classcache_name_entry * entry,
998 {
999  classcache_class_entry *clsen;
1001 
1002  assert(entry);
1003 
1004  /* iterate over all class entries */
1005  for (clsen = entry->classes; clsen; clsen = clsen->next) {
1006 
1007  /* check if this entry has already been loaded by initloader */
1008  for (lden = clsen->loaders; lden; lden = lden->next) {
1009  if (lden->loader == loader)
1010  return clsen; /* found */
1011  }
1012 
1013  /* check if loader is constrained to this entry */
1014  for (lden = clsen->constraints; lden; lden = lden->next) {
1015  if (lden->loader == loader)
1016  return clsen; /* found */
1017  }
1018  }
1019 
1020  /* not found */
1021  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 
1035 {
1038 
1039  assert(clsen);
1040 
1041  for (lden = clsen->loaders; lden; lden = next) {
1042  next = lden->next;
1044  }
1045  for (lden = clsen->constraints; lden; lden = next) {
1046  next = lden->next;
1048  }
1049 
1050  FREE(clsen, classcache_class_entry);
1051 }
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 
1066  classcache_class_entry * clsen)
1067 {
1068  classcache_class_entry **chain;
1069 
1070  assert(entry);
1071  assert(clsen);
1072 
1073  chain = &(entry->classes);
1074  while (*chain) {
1075  if (*chain == clsen) {
1076  *chain = clsen->next;
1078  return;
1079  }
1080  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 
1094 {
1095  classcache_class_entry *clsen;
1097 
1098  assert(entry);
1099 
1100  for (clsen = entry->classes; clsen; clsen = next) {
1101  next = clsen->next;
1103  }
1104 
1105  FREE(entry, classcache_name_entry);
1106 }
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 
1121 {
1122  u4 slot;
1123  classcache_name_entry *entry;
1125 
1126  for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1127  for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
1128  next = entry->hashlink;
1130  }
1131  }
1132 
1133  MFREE(hashtable_classcache.ptr, void*, hashtable_classcache.size);
1134  hashtable_classcache.size = 0;
1135  hashtable_classcache.entries = 0;
1136  hashtable_classcache.ptr = NULL;
1137 }
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)
1158  classloader_t * b,
1159  Utf8String classname)
1160 {
1162  classcache_class_entry *clsenA;
1163  classcache_class_entry *clsenB;
1164 
1165  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  if (a == b) {
1177  CLASSCACHE_COUNT(stat_trivial_constraints);
1178  return true;
1179  }
1180 
1181  CLASSCACHE_LOCK();
1182 
1183  en = classcache_new_name(classname);
1184 
1185  assert(en);
1186  CLASSCACHE_COUNT(stat_nontriv_constraints);
1187 
1188  /* find the entry loaded by / constrained to each loader */
1189  clsenA = classcache_find_loader(en, a);
1190  clsenB = classcache_find_loader(en, b);
1191 
1192  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  if (clsenA == clsenB)
1198  goto return_success;
1199 
1200  /* check if the entries can be merged */
1201  if (clsenA->classobj && clsenB->classobj
1202  && clsenA->classobj != clsenB->classobj) {
1203  /* no, the constraint is violated */
1204  exceptions_throw_linkageerror("loading constraint violated: ",
1205  clsenA->classobj);
1206  goto return_exception;
1207  }
1208 
1209  /* yes, merge the entries */
1210  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  if (!clsenA)
1218  clsenA = clsenB;
1219 
1220  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  clsenA = NEW(classcache_class_entry);
1226  clsenA->classobj = NULL;
1227  clsenA->loaders = NULL;
1228  clsenA->constraints = classcache_new_loader_entry(b, NULL);
1229  clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
1230 
1231  clsenA->next = en->classes;
1232  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  if (clsenB)
1239  b = a;
1240 
1241  /* loader b must be added to entry clsenA */
1242  clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
1243  }
1244  }
1245 
1246  return_success:
1248  return true;
1249 
1250  return_exception:
1252  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)
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  if (a == b) {
1286  return true;
1287  }
1288 
1289  /* get the parsed descriptor */
1290 
1291  assert(m);
1292  md = m->parseddesc;
1293  assert(md);
1294 
1295  /* constrain the return type */
1296 
1297  if (md->returntype.type == TYPE_ADR) {
1299  return false; /* exception */
1300  }
1301 
1302  /* constrain each reference type used in the parameters */
1303 
1304  td = md->paramtypes;
1305  i = md->paramcount;
1306  for (; i--; td++) {
1307  if (td->type != TYPE_ADR)
1308  continue;
1309 
1310  if (!classcache_add_constraint(a, b, td->classref->name))
1311  return false; /* exception */
1312  }
1313 
1314  /* everything ok */
1315  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 
1330 {
1332  classcache_class_entry *clsen;
1333  s4 number;
1334  u4 i;
1335 
1336  /* initialize class counter */
1337 
1338  number = 0;
1339 
1340  for (i = 0; i < hashtable_classcache.size; i++) {
1341  /* iterate over hashlink */
1342 
1343  for (en = (classcache_name_entry*) hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1344  /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1345 
1346  if (en->name[0] == '$')
1347  continue;
1348 
1349  /* iterate over classes with same name */
1350 
1351  for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1352  /* get only loaded classes */
1353 
1354  if (clsen->classobj != NULL)
1355  number++;
1356  }
1357  }
1358  }
1359 
1360  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 
1371 {
1372  s4 count;
1373 
1374  CLASSCACHE_LOCK();
1375 
1377 
1379 
1380  return count;
1381 }
1382 
1383 
1384 /* classcache_foreach_loaded_class *********************************************
1385 
1386  Calls the given function for each loaded class.
1387 
1388 *******************************************************************************/
1389 
1391  void *data)
1392 {
1394  classcache_class_entry *clsen;
1395  u4 i;
1396 
1397  CLASSCACHE_LOCK();
1398 
1399  /* look in every slot of the hashtable */
1400 
1401  for (i = 0; i < hashtable_classcache.size; i++) {
1402  /* iterate over hashlink */
1403 
1404  for (en = (classcache_name_entry*) hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
1405  /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
1406 
1407  if (en->name[0] == '$')
1408  continue;
1409 
1410  /* iterate over classes with same name */
1411 
1412  for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
1413  /* get only loaded classes */
1414 
1415  if (clsen->classobj != NULL) {
1416  (*func)(clsen->classobj, data);
1417  }
1418  }
1419  }
1420  }
1421 
1423 }
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 void classcache_debug_dump(FILE * file,Utf8String only)
1446 {
1448  classcache_class_entry *clsen;
1450  u4 slot;
1451 
1452  CLASSCACHE_LOCK();
1453 
1454  log_println("=== [loaded class cache] =====================================");
1455  log_println("hash size : %d", (int) hashtable_classcache.size);
1456  log_println("hash entries: %d", (int) hashtable_classcache.entries);
1457  log_println("");
1458 
1459  if (only) {
1460  c = classcache_lookup_name(only);
1461  slot = 0; /* avoid compiler warning */
1462  goto dump_it;
1463  }
1464 
1465  for (slot = 0; slot < hashtable_classcache.size; ++slot) {
1466  c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
1467 
1468 dump_it:
1469  for (; c; c = c->hashlink) {
1471  fprintf(file, "\n");
1472 
1473  /* iterate over all class entries */
1474  for (clsen = c->classes; clsen; clsen = clsen->next) {
1475  if (clsen->classobj) {
1476  log_println(" loaded %p", (void *) clsen->classobj);
1477  }
1478  else {
1479  log_println(" unresolved");
1480  }
1481 
1482  log_start();
1483  log_print(" loaders: ");
1484  for (lden = clsen->loaders; lden; lden = lden->next) {
1485  log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1486  }
1487  log_finish();
1488 
1489  log_start();
1490  log_print(" constraints: ");
1491  for (lden = clsen->constraints; lden; lden = lden->next) {
1492  log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
1493  }
1494  log_finish();
1495  }
1496  }
1497 
1498  if (only)
1499  break;
1500  }
1501  fprintf(file, "\n==============================================================\n\n");
1502 
1504 }
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  */
classcache_loader_entry * loaders
Definition: classcache.hpp:101
jlong jlong jlong jlong jint jmethodID jint slot
Definition: jvmti.h:497
classinfo * classcache_lookup_defined_or_initiated(classloader_t *loader, Utf8String classname)
Definition: classcache.cpp:662
#define CLASSCACHE_COUNTIF(cond, cnt)
Definition: classcache.cpp:203
classinfo * classcache_lookup(classloader_t *initloader, Utf8String classname)
Definition: classcache.cpp:564
bool classcache_add_constraints_for_params(classloader_t *a, classloader_t *b, methodinfo *m)
void exceptions_throw_linkageerror(const char *message, classinfo *c)
Definition: exceptions.cpp:833
#define NEW(type)
Definition: memory.hpp:93
static classcache_name_entry * classcache_new_name(Utf8String name)
Definition: classcache.cpp:468
#define FREE(ptr, type)
Definition: memory.hpp:94
static void classcache_free_class_entry(classcache_class_entry *clsen)
classcache_class_entry * next
Definition: classcache.hpp:103
s4 state
Definition: class.hpp:115
classinfo * classcache_store_defined(classinfo *cls)
Definition: classcache.cpp:917
classloader_t * classloader
Definition: class.hpp:151
void classcache_debug_dump(FILE *file, Utf8String only)
void classcache_free(void)
static void classcache_free_name_entry(classcache_name_entry *entry)
classloader_t * loader
Definition: classcache.hpp:108
hashtable hashtable_classcache
Definition: classcache.cpp:223
classinfo * classcache_store(classloader_t *initloader, classinfo *cls, bool mayfree)
Definition: classcache.cpp:730
Dummy implementation of a mutex.
Definition: mutex-none.hpp:33
#define CLASSCACHE_LOCK()
Definition: classcache.cpp:215
void utf_fprint_printable_ascii_classname(FILE *file, Utf8String u)
Definition: utf8.cpp:665
static classcache_class_entry * classcache_find_loader(classcache_name_entry *entry, classloader_t *loader)
Definition: classcache.cpp:995
size_t hash() const
Definition: utf8.hpp:137
JNIEnv jclass jobject const char * name
Definition: jvmti.h:312
void(* classcache_foreach_functionptr_t)(classinfo *, void *)
Definition: classcache.hpp:115
void log_finish(void)
Definition: logging.cpp:117
void log_println(const char *text,...)
Definition: logging.cpp:193
static void classcache_remove_class_entry(classcache_name_entry *en, classcache_class_entry *clsen)
Buffer & write_slash_to_dot(const char *)
write to buffer, replacing &#39;/&#39; by &#39;.&#39;
Definition: buffer.hpp:297
#define TRACESUBSYSTEMINITIALIZATION(text)
Definition: options.hpp:258
typedesc paramtypes[1]
Definition: descriptor.hpp:167
static classcache_loader_entry * classcache_new_loader_entry(classloader_t *loader, classcache_loader_entry *next)
Definition: classcache.cpp:278
void log_print(const char *text,...)
Definition: logging.cpp:149
classcache_class_entry * classes
Definition: classcache.hpp:95
classcache_loader_entry * constraints
Definition: classcache.hpp:102
Utf8String name
Definition: class.hpp:91
#define CLASSCACHE_INIT_SIZE
Definition: classcache.cpp:136
void exceptions_throw_internalerror(const char *message,...)
Definition: exceptions.cpp:805
void ** ptr
Definition: hashtable.hpp:781
void log_start(void)
Definition: logging.cpp:106
bool classcache_store_unique(classinfo *cls)
Definition: classcache.cpp:883
MIIterator i
Definition: classcache.hpp:106
typedesc returntype
Definition: descriptor.hpp:166
static classcache_loader_entry * classcache_merge_loaders(classcache_loader_entry *lista, classcache_loader_entry *listb)
Definition: classcache.cpp:309
int32_t s4
Definition: types.hpp:45
JNIEnv jclass jobject loader
Definition: jvmti.h:312
static void classcache_merge_class_entries(classcache_name_entry *en, classcache_class_entry *clsenA, classcache_class_entry *clsenB)
Definition: classcache.cpp:368
bool classcache_init(void)
Definition: classcache.cpp:247
static s4 classcache_number_of_loaded_classes(void)
static classcache_name_entry * classcache_lookup_name(Utf8String name)
Definition: classcache.cpp:423
uint32_t u4
Definition: types.hpp:46
methoddesc * parseddesc
Definition: method.hpp:78
void class_free(classinfo *c)
Definition: class.cpp:739
Utf8String name
Definition: classcache.hpp:93
static Mutex * classcache_hashtable_mutex
Definition: classcache.cpp:225
Buffer & write(char)
Definition: buffer.hpp:280
Definition: classcache.hpp:98
void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func, void *data)
static java_object_t * next
Definition: copy.c:43
s4 classcache_get_loaded_class_count(void)
bool classcache_add_constraint(classloader_t *a, classloader_t *b, Utf8String classname)
classcache_name_entry * hashlink
Definition: classcache.hpp:94
Buffer & writef(const char *fmt,...)
Definition: buffer.hpp:426
void hashtable_create(hashtable *hash, u4 size)
Definition: hashtable.cpp:38
classinfo * classcache_lookup_defined(classloader_t *defloader, Utf8String classname)
Definition: classcache.cpp:616
classcache_loader_entry * next
Definition: classcache.hpp:109
#define CLASSCACHE_UNLOCK()
Definition: classcache.cpp:216
classinfo * classobj
Definition: classcache.hpp:100
#define MFREE(ptr, type, num)
Definition: memory.hpp:97
const Utf8String name
Definition: references.hpp:48
Definition: classcache.hpp:91
constant_classref * classref
Definition: descriptor.hpp:135
#define CLASSCACHE_COUNT(cnt)
Definition: classcache.cpp:202