< prev index next >

src/share/vm/classfile/dictionary.cpp

Print this page

        

@@ -30,48 +30,49 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.hpp"
 #include "runtime/orderAccess.inline.hpp"
 #include "utilities/hashtable.inline.hpp"
 
-DictionaryEntry*  Dictionary::_current_class_entry = NULL;
-int               Dictionary::_current_class_index =    0;
-
 size_t Dictionary::entry_size() {
   if (DumpSharedSpaces) {
     return SystemDictionaryShared::dictionary_entry_size();
   } else {
     return sizeof(DictionaryEntry);
   }
 }
 
-Dictionary::Dictionary(int table_size)
-  : TwoOopHashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
-  _current_class_index = 0;
-  _current_class_entry = NULL;
-  _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
+Dictionary::Dictionary(ClassLoaderData* loader_data, int table_size)
+  : _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
 };
 
 
-Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
+Dictionary::Dictionary(ClassLoaderData* loader_data,
+                       int table_size, HashtableBucket<mtClass>* t,
                        int number_of_entries)
-  : TwoOopHashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
-  _current_class_index = 0;
-  _current_class_entry = NULL;
-  _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
+  : _loader_data(loader_data), Hashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
 };
 
-ProtectionDomainCacheEntry* Dictionary::cache_get(Handle protection_domain) {
-  return _pd_cache_table->get(protection_domain);
+Dictionary::~Dictionary() {
+  DictionaryEntry* probe = NULL;
+  for (int index = 0; index < table_size(); index++) {
+    for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
+      probe = *p;
+      *p = probe->next();
+      free_entry(probe);
+    }
+  }
+  assert(number_of_entries() == 0, "should have removed all entries");
+  assert(new_entry_free_list() == NULL, "entry present on Dictionary's free list");
+  free_buckets();
 }
 
-DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass,
-                                       ClassLoaderData* loader_data) {
-  DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::new_entry(hash, klass);
-  entry->set_loader_data(loader_data);
+DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass) {
+  DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::allocate_new_entry(hash, klass);
   entry->set_pd_set(NULL);
   assert(klass->is_instance_klass(), "Must be");
   if (DumpSharedSpaces) {
     SystemDictionaryShared::init_shared_dictionary_entry(klass, entry);
   }

@@ -84,11 +85,13 @@
   while (entry->pd_set() != NULL) {
     ProtectionDomainEntry* to_delete = entry->pd_set();
     entry->set_pd_set(to_delete->next());
     delete to_delete;
   }
-  Hashtable<InstanceKlass*, mtClass>::free_entry(entry);
+  // Unlink from the Hashtable prior to freeing
+  unlink_entry(entry);
+  FREE_C_HEAP_ARRAY(char, entry);
 }
 
 
 bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
 #ifdef ASSERT

@@ -125,11 +128,11 @@
 
 
 void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   if (!contains_protection_domain(protection_domain())) {
-    ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
+    ProtectionDomainCacheEntry* entry = SystemDictionary::cache_get(protection_domain);
     ProtectionDomainEntry* new_head =
                 new ProtectionDomainEntry(entry, _pd_set);
     // Warning: Preserve store ordering.  The SystemDictionary is read
     //          without locks.  The new ProtectionDomainEntry must be
     //          complete before other threads can be allowed to see it

@@ -145,90 +148,47 @@
 
 
 void Dictionary::do_unloading() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
-  // Remove unloadable entries and classes from system dictionary
+  // The NULL class loader doesn't initiate loading classes from other class loaders
+  if (loader_data() == ClassLoaderData::the_null_class_loader_data()) {
+    return;
+  }
+
+  // Remove unloaded entries and classes from this dictionary
   DictionaryEntry* probe = NULL;
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
       probe = *p;
-      Klass* e = probe->klass();
-      ClassLoaderData* loader_data = probe->loader_data();
-
-      InstanceKlass* ik = InstanceKlass::cast(e);
-
-      // Only unload classes that are not strongly reachable
-      if (!is_strongly_reachable(loader_data, e)) {
-        // Entry was not visited in phase1 (negated test from phase1)
-        assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader");
+      InstanceKlass* ik = probe->klass();
         ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
 
-        // Do we need to delete this system dictionary entry?
-        bool purge_entry = false;
-
-        // Do we need to delete this system dictionary entry?
-        if (loader_data->is_unloading()) {
-          // If the loader is not live this entry should always be
-          // removed (will never be looked up again).
-          purge_entry = true;
-        } else {
-          // The loader in this entry is alive. If the klass is dead,
+      // If the klass that this loader initiated is dead,
           // (determined by checking the defining class loader)
-          // the loader must be an initiating loader (rather than the
-          // defining loader). Remove this entry.
+      // remove this entry.
           if (k_def_class_loader_data->is_unloading()) {
-            // If we get here, the class_loader_data must not be the defining
-            // loader, it must be an initiating one.
-            assert(k_def_class_loader_data != loader_data,
+        assert(k_def_class_loader_data != loader_data(),
                    "cannot have live defining loader and unreachable klass");
-            // Loader is live, but class and its defining loader are dead.
-            // Remove the entry. The class is going away.
-            purge_entry = true;
-          }
-        }
-
-        if (purge_entry) {
           *p = probe->next();
-          if (probe == _current_class_entry) {
-            _current_class_entry = NULL;
-          }
           free_entry(probe);
           continue;
         }
-      }
       p = probe->next_addr();
     }
   }
 }
 
-void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
-  // Do strong roots marking if the closures are the same.
-  if (strong == weak || !ClassUnloading) {
-    // Only the protection domain oops contain references into the heap. Iterate
-    // over all of them.
-    _pd_cache_table->oops_do(strong);
-  } else {
-   if (weak != NULL) {
-     _pd_cache_table->oops_do(weak);
-   }
-  }
-}
-
-
 void Dictionary::remove_classes_in_error_state() {
   assert(DumpSharedSpaces, "supported only when dumping");
   DictionaryEntry* probe = NULL;
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
       probe = *p;
-      InstanceKlass* ik = InstanceKlass::cast(probe->klass());
+      InstanceKlass* ik = probe->klass();
       if (ik->is_in_error_state()) { // purge this entry
         *p = probe->next();
-        if (probe == _current_class_entry) {
-          _current_class_entry = NULL;
-        }
         free_entry(probe);
         ResourceMark rm;
         tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name());
         continue;
       }

@@ -237,92 +197,64 @@
     }
   }
 }
 
 //   Just the classes from defining class loaders
-void Dictionary::classes_do(void f(Klass*)) {
+void Dictionary::classes_do(void f(InstanceKlass*)) {
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry* probe = bucket(index);
                           probe != NULL;
                           probe = probe->next()) {
-      Klass* k = probe->klass();
-      if (probe->loader_data() == k->class_loader_data()) {
+      InstanceKlass* k = probe->klass();
+      if (loader_data() == k->class_loader_data()) {
         f(k);
       }
     }
   }
 }
 
 // Added for initialize_itable_for_klass to handle exceptions
 //   Just the classes from defining class loaders
-void Dictionary::classes_do(void f(Klass*, TRAPS), TRAPS) {
+void Dictionary::classes_do(void f(InstanceKlass*, TRAPS), TRAPS) {
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry* probe = bucket(index);
                           probe != NULL;
                           probe = probe->next()) {
-      Klass* k = probe->klass();
-      if (probe->loader_data() == k->class_loader_data()) {
+      InstanceKlass* k = probe->klass();
+      if (loader_data() == k->class_loader_data()) {
         f(k, CHECK);
       }
     }
   }
 }
 
-//   All classes, and their class loaders
-// Don't iterate over placeholders
-void Dictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
+// All classes, and their class loaders, including initiating class loaders
+void Dictionary::all_entries_do(void f(InstanceKlass*, ClassLoaderData*)) {
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry* probe = bucket(index);
                           probe != NULL;
                           probe = probe->next()) {
-      Klass* k = probe->klass();
-      f(k, probe->loader_data());
+      InstanceKlass* k = probe->klass();
+      f(k, loader_data());
     }
   }
 }
 
-void Dictionary::oops_do(OopClosure* f) {
-  // Only the protection domain oops contain references into the heap. Iterate
-  // over all of them.
-  _pd_cache_table->oops_do(f);
-}
-
-void Dictionary::unlink(BoolObjectClosure* is_alive) {
-  // Only the protection domain cache table may contain references to the heap
-  // that need to be unlinked.
-  _pd_cache_table->unlink(is_alive);
-}
-
-InstanceKlass* Dictionary::try_get_next_class() {
-  while (true) {
-    if (_current_class_entry != NULL) {
-      InstanceKlass* k = _current_class_entry->klass();
-      _current_class_entry = _current_class_entry->next();
-      return k;
-    }
-    _current_class_index = (_current_class_index + 1) % table_size();
-    _current_class_entry = bucket(_current_class_index);
-  }
-  // never reached
-}
 
 // Add a loaded class to the system dictionary.
 // Readers of the SystemDictionary aren't always locked, so _buckets
 // is volatile. The store of the next field in the constructor is
 // also cast to volatile;  we do this to ensure store order is maintained
 // by the compilers.
 
-void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data,
+void Dictionary::add_klass(int index, unsigned int hash, Symbol* class_name,
                            InstanceKlass* obj) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   assert(obj != NULL, "adding NULL obj");
   assert(obj->name() == class_name, "sanity check on name");
-  assert(loader_data != NULL, "Must be non-NULL");
 
-  unsigned int hash = compute_hash(class_name, loader_data);
-  int index = hash_to_index(hash);
-  DictionaryEntry* entry = new_entry(hash, obj, loader_data);
+  DictionaryEntry* entry = new_entry(hash, obj);
   add_entry(index, entry);
 }
 
 
 // This routine does not lock the system dictionary.

@@ -333,62 +265,63 @@
 // be updated in an MT-safe manner).
 //
 // Callers should be aware that an entry could be added just after
 // _buckets[index] is read here, so the caller will not see the new entry.
 DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
-                                       Symbol* class_name,
-                                       ClassLoaderData* loader_data) {
+                                       Symbol* class_name) {
   for (DictionaryEntry* entry = bucket(index);
                         entry != NULL;
                         entry = entry->next()) {
-    if (entry->hash() == hash && entry->equals(class_name, loader_data)) {
+    if (entry->hash() == hash && entry->equals(class_name)) {
+      if (!DumpSharedSpaces || SystemDictionaryShared::is_builtin(entry)) {
       return entry;
     }
   }
+  }
   return NULL;
 }
 
 
 InstanceKlass* Dictionary::find(int index, unsigned int hash, Symbol* name,
-                                ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
-  DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
+                                Handle protection_domain) {
+  DictionaryEntry* entry = get_entry(index, hash, name);
   if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
     return entry->klass();
   } else {
     return NULL;
   }
 }
 
 
 InstanceKlass* Dictionary::find_class(int index, unsigned int hash,
-                                      Symbol* name, ClassLoaderData* loader_data) {
+                                      Symbol* name) {
   assert_locked_or_safepoint(SystemDictionary_lock);
-  assert (index == index_for(name, loader_data), "incorrect index?");
+  assert (index == index_for(name), "incorrect index?");
 
-  DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
+  DictionaryEntry* entry = get_entry(index, hash, name);
   return (entry != NULL) ? entry->klass() : NULL;
 }
 
 
 // Variant of find_class for shared classes.  No locking required, as
 // that table is static.
 
 InstanceKlass* Dictionary::find_shared_class(int index, unsigned int hash,
                                              Symbol* name) {
-  assert (index == index_for(name, NULL), "incorrect index?");
+  assert (index == index_for(name), "incorrect index?");
 
-  DictionaryEntry* entry = get_entry(index, hash, name, NULL);
+  DictionaryEntry* entry = get_entry(index, hash, name);
   return (entry != NULL) ? entry->klass() : NULL;
 }
 
 
 void Dictionary::add_protection_domain(int index, unsigned int hash,
                                        InstanceKlass* klass,
-                                       ClassLoaderData* loader_data, Handle protection_domain,
+                                       Handle protection_domain,
                                        TRAPS) {
   Symbol*  klass_name = klass->name();
-  DictionaryEntry* entry = get_entry(index, hash, klass_name, loader_data);
+  DictionaryEntry* entry = get_entry(index, hash, klass_name);
 
   assert(entry != NULL,"entry must be present, we just created it");
   assert(protection_domain() != NULL,
          "real protection domain should be present");
 

@@ -399,13 +332,12 @@
 }
 
 
 bool Dictionary::is_valid_protection_domain(int index, unsigned int hash,
                                             Symbol* name,
-                                            ClassLoaderData* loader_data,
                                             Handle protection_domain) {
-  DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
+  DictionaryEntry* entry = get_entry(index, hash, name);
   return entry->is_valid_protection_domain(protection_domain);
 }
 
 
 void Dictionary::reorder_dictionary() {

@@ -431,14 +363,13 @@
     master_list = master_list->next();
     p->set_next(NULL);
     Symbol* class_name = p->klass()->name();
     // Since the null class loader data isn't copied to the CDS archive,
     // compute the hash with NULL for loader data.
-    unsigned int hash = compute_hash(class_name, NULL);
+    unsigned int hash = compute_hash(class_name);
     int index = hash_to_index(hash);
     p->set_hash(hash);
-    p->set_loader_data(NULL);   // loader_data isn't copied to CDS
     p->set_next(bucket(index));
     set_entry(index, p);
   }
 }
 

@@ -515,54 +446,49 @@
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry* probe = bucket(index);
                           probe != NULL;
                           probe = probe->next()) {
       Klass* e = probe->klass();
-      ClassLoaderData* loader_data =  probe->loader_data();
       bool is_defining_class =
-         (loader_data == e->class_loader_data());
+         (loader_data() == e->class_loader_data());
       if (details) {
         tty->print("%4d: ", index);
       }
       tty->print("%s%s", ((!details) || is_defining_class) ? " " : "^",
                  e->external_name());
 
       if (details) {
         tty->print(", loader ");
-        if (loader_data != NULL) {
-          loader_data->print_value();
-        } else {
-          tty->print("NULL");
-        }
+        e->class_loader_data()->print_value();
       }
       tty->cr();
     }
   }
-
-  if (details) {
-    tty->cr();
-    _pd_cache_table->print();
-  }
   tty->cr();
 }
 
 void DictionaryEntry::verify() {
   Klass* e = klass();
-  ClassLoaderData* cld = loader_data();
   guarantee(e->is_instance_klass(),
                           "Verify of system dictionary failed");
+  e->verify();
+  verify_protection_domain_set();
+}
+
+void Dictionary::verify() {
+  guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
+
+  ClassLoaderData* cld = loader_data();
   // class loader must be present;  a null class loader is the
   // boostrap loader
   guarantee(cld != NULL || DumpSharedSpaces ||
             cld->class_loader() == NULL ||
             cld->class_loader()->is_instance(),
             "checking type of class_loader");
-  e->verify();
-  verify_protection_domain_set();
-}
 
-void Dictionary::verify() {
-  guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
-  verify_table<DictionaryEntry>("System Dictionary");
-  _pd_cache_table->verify();
+  ResourceMark rm;
+  
+  stringStream tempst;
+  tempst.print("System Dictionary for %s", cld->loader_name());
+  verify_table<DictionaryEntry>(tempst.as_string());
 }
 
< prev index next >