--- 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();
}