hotspot/src/share/vm/classfile/dictionary.cpp
changeset 46554 aa1cfd918c4f
parent 46475 75902cea18af
child 46701 f559541c0daa
--- a/hotspot/src/share/vm/classfile/dictionary.cpp	Wed Jul 05 23:44:18 2017 +0200
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp	Thu Jun 22 00:51:07 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -26,6 +26,7 @@
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/sharedClassUtil.hpp"
 #include "classfile/dictionary.hpp"
+#include "classfile/protectionDomainCache.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/systemDictionaryShared.hpp"
 #include "memory/iterator.hpp"
@@ -46,7 +47,7 @@
 }
 
 Dictionary::Dictionary(int table_size)
-  : TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size()) {
+  : TwoOopHashtable<InstanceKlass*, mtClass>(table_size, (int)entry_size()) {
   _current_class_index = 0;
   _current_class_entry = NULL;
   _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
@@ -55,19 +56,19 @@
 
 Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
                        int number_of_entries)
-  : TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size(), t, 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);
 };
 
-ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) {
+ProtectionDomainCacheEntry* Dictionary::cache_get(Handle protection_domain) {
   return _pd_cache_table->get(protection_domain);
 }
 
-DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
+DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass,
                                        ClassLoaderData* loader_data) {
-  DictionaryEntry* entry = (DictionaryEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
+  DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::new_entry(hash, klass);
   entry->set_loader_data(loader_data);
   entry->set_pd_set(NULL);
   assert(klass->is_instance_klass(), "Must be");
@@ -85,7 +86,7 @@
     entry->set_pd_set(to_delete->next());
     delete to_delete;
   }
-  Hashtable<Klass*, mtClass>::free_entry(entry);
+  Hashtable<InstanceKlass*, mtClass>::free_entry(entry);
 }
 
 
@@ -123,9 +124,9 @@
 }
 
 
-void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) {
+void DictionaryEntry::add_protection_domain(Dictionary* dict, Handle protection_domain) {
   assert_locked_or_safepoint(SystemDictionary_lock);
-  if (!contains_protection_domain(protection_domain)) {
+  if (!contains_protection_domain(protection_domain())) {
     ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
     ProtectionDomainEntry* new_head =
                 new ProtectionDomainEntry(entry, _pd_set);
@@ -147,7 +148,6 @@
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
 
   // Remove unloadable entries and classes from system dictionary
-  // The placeholder array has been handled in always_strong_oops_do.
   DictionaryEntry* probe = NULL;
   for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
@@ -157,7 +157,7 @@
 
       InstanceKlass* ik = InstanceKlass::cast(e);
 
-      // Non-unloadable classes were handled in always_strong_oops_do
+      // 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");
@@ -202,25 +202,18 @@
 }
 
 void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
-  // Skip the strong roots probe marking if the closures are the same.
-  if (strong == weak) {
-    oops_do(strong);
-    return;
+  // 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);
+   }
   }
+}
 
-  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->set_strongly_reachable();
-      }
-    }
-  }
-  _pd_cache_table->roots_oops_do(strong, weak);
-}
 
 void Dictionary::remove_classes_in_error_state() {
   assert(DumpSharedSpaces, "supported only when dumping");
@@ -245,44 +238,6 @@
   }
 }
 
-void Dictionary::always_strong_oops_do(OopClosure* blk) {
-  // Follow all system classes and temporary placeholders in dictionary; only
-  // protection domain oops contain references into the heap. In a first
-  // pass over the system dictionary determine which need to be treated as
-  // strongly reachable and mark them as such.
-  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->set_strongly_reachable();
-      }
-    }
-  }
-  // Then iterate over the protection domain cache to apply the closure on the
-  // previously marked ones.
-  _pd_cache_table->always_strong_oops_do(blk);
-}
-
-
-void Dictionary::always_strong_classes_do(KlassClosure* closure) {
-  // 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)) {
-        closure->do_klass(e);
-      }
-    }
-  }
-}
-
-
 //   Just the classes from defining class loaders
 void Dictionary::classes_do(void f(Klass*)) {
   for (int index = 0; index < table_size(); index++) {
@@ -331,30 +286,16 @@
   _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()) {
-      Klass* k = probe->klass();
-      if (probe->loader_data() == k->class_loader_data()) {
-        // only take klass is we have the entry with the defining class loader
-        InstanceKlass::cast(k)->methods_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);
 }
 
-Klass* Dictionary::try_get_next_class() {
+InstanceKlass* Dictionary::try_get_next_class() {
   while (true) {
     if (_current_class_entry != NULL) {
-      Klass* k = _current_class_entry->klass();
+      InstanceKlass* k = _current_class_entry->klass();
       _current_class_entry = _current_class_entry->next();
       return k;
     }
@@ -371,15 +312,15 @@
 // by the compilers.
 
 void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data,
-                           KlassHandle obj) {
+                           InstanceKlass* obj) {
   assert_locked_or_safepoint(SystemDictionary_lock);
-  assert(obj() != NULL, "adding NULL obj");
-  assert(obj()->name() == class_name, "sanity check on name");
+  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, loader_data);
   add_entry(index, entry);
 }
 
@@ -396,22 +337,19 @@
 DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
                                        Symbol* class_name,
                                        ClassLoaderData* loader_data) {
-  DEBUG_ONLY(_lookup_count++);
   for (DictionaryEntry* entry = bucket(index);
                         entry != NULL;
                         entry = entry->next()) {
     if (entry->hash() == hash && entry->equals(class_name, loader_data)) {
-      DEBUG_ONLY(bucket_count_hit(index));
       return entry;
     }
-    DEBUG_ONLY(_lookup_length++);
   }
   return NULL;
 }
 
 
-Klass* Dictionary::find(int index, unsigned int hash, Symbol* name,
-                          ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
+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);
   if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
     return entry->klass();
@@ -421,30 +359,30 @@
 }
 
 
-Klass* Dictionary::find_class(int index, unsigned int hash,
-                                Symbol* name, ClassLoaderData* loader_data) {
+InstanceKlass* Dictionary::find_class(int index, unsigned int hash,
+                                      Symbol* name, ClassLoaderData* loader_data) {
   assert_locked_or_safepoint(SystemDictionary_lock);
   assert (index == index_for(name, loader_data), "incorrect index?");
 
   DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
-  return (entry != NULL) ? entry->klass() : (Klass*)NULL;
+  return (entry != NULL) ? entry->klass() : NULL;
 }
 
 
 // Variant of find_class for shared classes.  No locking required, as
 // that table is static.
 
-Klass* Dictionary::find_shared_class(int index, unsigned int hash,
-                                       Symbol* name) {
+InstanceKlass* Dictionary::find_shared_class(int index, unsigned int hash,
+                                             Symbol* name) {
   assert (index == index_for(name, NULL), "incorrect index?");
 
   DictionaryEntry* entry = get_entry(index, hash, name, NULL);
-  return (entry != NULL) ? entry->klass() : (Klass*)NULL;
+  return (entry != NULL) ? entry->klass() : NULL;
 }
 
 
 void Dictionary::add_protection_domain(int index, unsigned int hash,
-                                       instanceKlassHandle klass,
+                                       InstanceKlass* klass,
                                        ClassLoaderData* loader_data, Handle protection_domain,
                                        TRAPS) {
   Symbol*  klass_name = klass->name();
@@ -454,7 +392,7 @@
   assert(protection_domain() != NULL,
          "real protection domain should be present");
 
-  entry->add_protection_domain(this, protection_domain());
+  entry->add_protection_domain(this, protection_domain);
 
   assert(entry->contains_protection_domain(protection_domain()),
          "now protection domain should be present");
@@ -505,171 +443,6 @@
 }
 
 
-unsigned int ProtectionDomainCacheTable::compute_hash(oop protection_domain) {
-  return (unsigned int)(protection_domain->identity_hash());
-}
-
-int ProtectionDomainCacheTable::index_for(oop protection_domain) {
-  return hash_to_index(compute_hash(protection_domain));
-}
-
-ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
-  : Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
-{
-}
-
-void ProtectionDomainCacheTable::unlink(BoolObjectClosure* is_alive) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be");
-  for (int i = 0; i < table_size(); ++i) {
-    ProtectionDomainCacheEntry** p = bucket_addr(i);
-    ProtectionDomainCacheEntry* entry = bucket(i);
-    while (entry != NULL) {
-      if (is_alive->do_object_b(entry->literal())) {
-        p = entry->next_addr();
-      } else {
-        *p = entry->next();
-        free_entry(entry);
-      }
-      entry = *p;
-    }
-  }
-}
-
-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::roots_oops_do(OopClosure* strong, OopClosure* weak) {
-  for (int index = 0; index < table_size(); index++) {
-    for (ProtectionDomainCacheEntry* probe = bucket(index);
-                                     probe != NULL;
-                                     probe = probe->next()) {
-      if (probe->is_strongly_reachable()) {
-        probe->reset_strongly_reachable();
-        probe->oops_do(strong);
-      } else {
-        if (weak != NULL) {
-          probe->oops_do(weak);
-        }
-      }
-    }
-  }
-}
-
-uint ProtectionDomainCacheTable::bucket_size() {
-  return sizeof(ProtectionDomainCacheEntry);
-}
-
-#ifndef PRODUCT
-void ProtectionDomainCacheTable::print() {
-  tty->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
-                table_size(), number_of_entries());
-  for (int index = 0; index < table_size(); index++) {
-    for (ProtectionDomainCacheEntry* probe = bucket(index);
-                                     probe != NULL;
-                                     probe = probe->next()) {
-      probe->print();
-    }
-  }
-}
-
-void ProtectionDomainCacheEntry::print() {
-  tty->print_cr("entry " PTR_FORMAT " value " PTR_FORMAT " strongly_reachable %d next " PTR_FORMAT,
-                p2i(this), p2i(literal()), _strongly_reachable, p2i(next()));
-}
-#endif
-
-void ProtectionDomainCacheTable::verify() {
-  int element_count = 0;
-  for (int index = 0; index < table_size(); index++) {
-    for (ProtectionDomainCacheEntry* probe = bucket(index);
-                                     probe != NULL;
-                                     probe = probe->next()) {
-      probe->verify();
-      element_count++;
-    }
-  }
-  guarantee(number_of_entries() == element_count,
-            "Verify of protection domain cache table failed");
-  DEBUG_ONLY(verify_lookup_length((double)number_of_entries() / table_size(), "Domain Cache Table"));
-}
-
-void ProtectionDomainCacheEntry::verify() {
-  guarantee(literal()->is_oop(), "must be an oop");
-}
-
-void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f) {
-  // the caller marked the protection domain cache entries that we need to apply
-  // the closure on. Only process them.
-  for (int index = 0; index < table_size(); index++) {
-    for (ProtectionDomainCacheEntry* probe = bucket(index);
-                                     probe != NULL;
-                                     probe = probe->next()) {
-      if (probe->is_strongly_reachable()) {
-        probe->reset_strongly_reachable();
-        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))
 {
@@ -731,7 +504,6 @@
 
 void Dictionary::print(bool details) {
   ResourceMark rm;
-  HandleMark   hm;
 
   if (details) {
     tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
@@ -773,115 +545,24 @@
   tty->cr();
 }
 
-#ifdef ASSERT
-void Dictionary::printPerformanceInfoDetails() {
-  if (log_is_enabled(Info, hashtables)) {
-    ResourceMark rm;
-    HandleMark   hm;
-
-    log_info(hashtables)(" ");
-    log_info(hashtables)("Java system dictionary (table_size=%d, classes=%d)",
-                            table_size(), number_of_entries());
-    log_info(hashtables)("1st number: the bucket index");
-    log_info(hashtables)("2nd number: the hit percentage for this bucket");
-    log_info(hashtables)("3rd number: the entry's index within this bucket");
-    log_info(hashtables)("4th number: the hash index of this entry");
-    log_info(hashtables)(" ");
-
-    // find top buckets with highest lookup count
-#define TOP_COUNT 16
-    int topItemsIndicies[TOP_COUNT];
-    for (int i = 0; i < TOP_COUNT; i++) {
-      topItemsIndicies[i] = i;
-    }
-    double total = 0.0;
-    for (int i = 0; i < table_size(); i++) {
-      // find the total count number, so later on we can
-      // express bucket lookup count as a percentage of all lookups
-      unsigned value = bucket_hits(i);
-      total += value;
-
-      // find the top entry with min value
-      int min_index = 0;
-      unsigned min_value = bucket_hits(topItemsIndicies[min_index]);
-      for (int j = 1; j < TOP_COUNT; j++) {
-        unsigned top_value = bucket_hits(topItemsIndicies[j]);
-        if (top_value < min_value) {
-          min_value = top_value;
-          min_index = j;
-        }
-      }
-      // if the bucket loookup value is bigger than the top buckets min
-      // move that bucket index into the top list
-      if (value > min_value) {
-        topItemsIndicies[min_index] = i;
-      }
-    }
-
-    for (int index = 0; index < table_size(); index++) {
-      double percentage = 100.0 * (double)bucket_hits(index)/total;
-      int chain = 0;
-      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());
-        log_info(hashtables)("%4d: %5.2f%%: %3d: %10u: %s, loader %s",
-                                index, percentage, chain, probe->hash(), e->external_name(),
-                                (loader_data != NULL) ? loader_data->loader_name() : "NULL");
-
-        chain++;
-      }
-      if (chain == 0) {
-        log_info(hashtables)("%4d:", index+1);
-      }
-    }
-    log_info(hashtables)(" ");
-
-    // print out the TOP_COUNT of buckets with highest lookup count (unsorted)
-    log_info(hashtables)("Top %d buckets:", TOP_COUNT);
-    for (int i = 0; i < TOP_COUNT; i++) {
-      log_info(hashtables)("%4d: hits %5.2f%%",
-                              topItemsIndicies[i],
-                                100.0*(double)bucket_hits(topItemsIndicies[i])/total);
-    }
-  }
+void DictionaryEntry::verify() {
+  Klass* e = klass();
+  ClassLoaderData* cld = loader_data();
+  guarantee(e->is_instance_klass(),
+                          "Verify of system dictionary failed");
+  // 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();
 }
-#endif // ASSERT
 
 void Dictionary::verify() {
   guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
-
-  int element_count = 0;
-  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();
-      guarantee(e->is_instance_klass(),
-                              "Verify of system dictionary failed");
-      // class loader must be present;  a null class loader is the
-      // boostrap loader
-      guarantee(loader_data != NULL || DumpSharedSpaces ||
-                loader_data->class_loader() == NULL ||
-                loader_data->class_loader()->is_instance(),
-                "checking type of class_loader");
-      e->verify();
-      probe->verify_protection_domain_set();
-      element_count++;
-    }
-  }
-  guarantee(number_of_entries() == element_count,
-            "Verify of system dictionary failed");
-#ifdef ASSERT
-  if (!verify_lookup_length((double)number_of_entries() / table_size(), "System Dictionary")) {
-    this->printPerformanceInfoDetails();
-  }
-#endif // ASSERT
-
+  verify_table<DictionaryEntry>("System Dictionary");
   _pd_cache_table->verify();
 }