src/share/vm/classfile/dictionary.cpp

Print this page
rev 5310 : imported patch ioi_original_patch

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -36,21 +36,25 @@
 
 Dictionary::Dictionary(int table_size)
   : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry)) {
   _current_class_index = 0;
   _current_class_entry = NULL;
+  _pd_cache_table = new ProtectionDomainCacheTable(137);
 };
 
 
-
 Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
                        int number_of_entries)
   : TwoOopHashtable<Klass*, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
   _current_class_index = 0;
   _current_class_entry = NULL;
+  _pd_cache_table = new ProtectionDomainCacheTable(137);
 };
 
+ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) {
+  return _pd_cache_table->get(protection_domain);
+}
 
 DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
                                        ClassLoaderData* loader_data) {
   DictionaryEntry* entry = (DictionaryEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
   entry->set_loader_data(loader_data);

@@ -63,10 +67,14 @@
 void Dictionary::free_entry(DictionaryEntry* entry) {
   // avoid recursion when deleting linked list
   while (entry->pd_set() != NULL) {
     ProtectionDomainEntry* to_delete = entry->pd_set();
     entry->set_pd_set(to_delete->next());
+    ProtectionDomainCacheEntry* cache = to_delete->release_pd_cache();
+    if (cache != NULL) {
+      _pd_cache_table->free(cache);
+    }
     delete to_delete;
   }
   Hashtable<Klass*, mtClass>::free_entry(entry);
 }
 

@@ -103,15 +111,16 @@
   }
   return false;
 }
 
 
-void DictionaryEntry::add_protection_domain(oop protection_domain) {
+void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   if (!contains_protection_domain(protection_domain)) {
+    ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
     ProtectionDomainEntry* new_head =
-                new ProtectionDomainEntry(protection_domain, _pd_set);
+                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
     //          via a store to _pd_set.
     OrderAccess::release_store_ptr(&_pd_set, new_head);

@@ -191,22 +200,34 @@
   return class_was_unloaded;
 }
 
 
 void Dictionary::always_strong_oops_do(OopClosure* blk) {
+  // This code is not multi-thread safe, but it should be called only
+  // by GC thread.
+  static int scan_generation = 0;
+  scan_generation++;
+  if (scan_generation == 0) {
+    // Wrapped around 32-bit. Never use 0 -- it's the initial value of
+    // ProtectionDomainCacheEntry::_scan_generation.
+    scan_generation = 1;
+  }
+
   // Follow all system classes and temporary placeholders in dictionary
   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();
       if (is_strongly_reachable(loader_data, e)) {
-        probe->protection_domain_set_oops_do(blk);
+        probe->set_strongly_reachable(scan_generation);
       }
     }
   }
+
+  _pd_cache_table->always_strong_oops_do(blk, scan_generation);
 }
 
 
 void Dictionary::always_strong_classes_do(KlassClosure* closure) {
   // Follow all system classes and temporary placeholders in dictionary

@@ -264,22 +285,14 @@
       f(k, probe->loader_data());
     }
   }
 }
 
-
 void Dictionary::oops_do(OopClosure* f) {
-  for (int index = 0; index < table_size(); index++) {
-    for (DictionaryEntry* probe = bucket(index);
-                          probe != NULL;
-                          probe = probe->next()) {
-      probe->protection_domain_set_oops_do(f);
-    }
-  }
+  _pd_cache_table->oops_do(f);
 }
 
-
 void Dictionary::methods_do(void f(Method*)) {
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry* probe = bucket(index);
                           probe != NULL;
                           probe = probe->next()) {

@@ -290,11 +303,10 @@
       }
     }
   }
 }
 
-
 Klass* Dictionary::try_get_next_class() {
   while (true) {
     if (_current_class_entry != NULL) {
       Klass* k = _current_class_entry->klass();
       _current_class_entry = _current_class_entry->next();

@@ -304,11 +316,10 @@
     _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.

@@ -394,11 +405,11 @@
 
   assert(entry != NULL,"entry must be present, we just created it");
   assert(protection_domain() != NULL,
          "real protection domain should be present");
 
-  entry->add_protection_domain(protection_domain());
+  entry->add_protection_domain(this, protection_domain());
 
   assert(entry->contains_protection_domain(protection_domain()),
          "now protection domain should be present");
 }
 

@@ -444,10 +455,89 @@
     p->set_next(bucket(index));
     set_entry(index, p);
   }
 }
 
+ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
+  : Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
+{
+}
+
+void ProtectionDomainCacheTable::oops_do(OopClosure* f) {
+  for (int index = 0; index < table_size(); index++) {
+    for (ProtectionDomainCacheEntry* probe = bucket(index);
+                                     probe != NULL;
+                                     probe = probe->next()) {
+      probe->oops_do(f);
+    }
+  }
+}
+
+
+void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f, int gen) {
+  for (int index = 0; index < table_size(); index++) {
+    for (ProtectionDomainCacheEntry* probe = bucket(index);
+                                     probe != NULL;
+                                     probe = probe->next()) {
+      if (probe->is_strongly_reachable(gen)) {
+        probe->oops_do(f);
+      }
+    }
+  }
+}
+
+ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domain) {
+  unsigned int hash = compute_hash(protection_domain);
+  int index = hash_to_index(hash);
+
+  ProtectionDomainCacheEntry* entry = find_entry(index, protection_domain);
+  if (entry == NULL) {
+    entry = add_entry(index, hash, protection_domain);
+  }
+  return entry;
+}
+
+ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oop protection_domain) {
+  for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) {
+    if (e->protection_domain() == protection_domain) {
+      return e;
+    }
+  }
+
+  return NULL;
+}
+
+ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, oop protection_domain) {
+  assert_locked_or_safepoint(SystemDictionary_lock);
+  assert(index == index_for(protection_domain), "incorrect index?");
+  assert(find_entry(index, protection_domain) == NULL, "no double entry");
+
+  ProtectionDomainCacheEntry* p = new_entry(hash, protection_domain);
+  Hashtable<oop, mtClass>::add_entry(index, p);
+  return p;
+}
+
+void ProtectionDomainCacheTable::free(ProtectionDomainCacheEntry* to_delete) {
+  unsigned int hash = compute_hash(to_delete->protection_domain());
+  int index = hash_to_index(hash);
+
+  ProtectionDomainCacheEntry** p = bucket_addr(index);
+  ProtectionDomainCacheEntry* entry = bucket(index);
+  while (true) {
+    assert(entry != NULL, "sanity");
+
+    if (entry == to_delete) {
+      *p = entry->next();
+      Hashtable<oop, mtClass>::free_entry(entry);
+      break;
+    } else {
+      p = entry->next_addr();
+      entry = *p;
+    }
+  }
+}
+
 SymbolPropertyTable::SymbolPropertyTable(int table_size)
   : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
 {
 }
 SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t,