--- a/src/hotspot/share/classfile/systemDictionary.cpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Thu Oct 17 20:53:35 2019 +0100
@@ -47,6 +47,7 @@
#include "compiler/compileBroker.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/oopStorage.inline.hpp"
+#include "gc/shared/oopStorageSet.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/interpreter.hpp"
#include "jfr/jfrEvents.hpp"
@@ -98,7 +99,6 @@
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
ProtectionDomainCacheTable* SystemDictionary::_pd_cache_table = NULL;
-int SystemDictionary::_number_of_modifications = 0;
oop SystemDictionary::_system_loader_lock_obj = NULL;
InstanceKlass* SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT]
@@ -115,9 +115,6 @@
const int defaultProtectionDomainCacheSize = 1009;
-OopStorage* SystemDictionary::_vm_weak_oop_storage = NULL;
-
-
// ----------------------------------------------------------------------------
// Java-level SystemLoader and PlatformLoader
@@ -180,7 +177,7 @@
return false;
}
return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass() ||
- oopDesc::equals(class_loader, _java_system_loader));
+ class_loader == _java_system_loader);
}
// Returns true if the passed class loader is the platform class loader.
@@ -396,7 +393,7 @@
if ((childk != NULL ) && (is_superclass) &&
((quicksuperk = childk->java_super()) != NULL) &&
((quicksuperk->name() == super_name) &&
- (oopDesc::equals(quicksuperk->class_loader(), class_loader())))) {
+ (quicksuperk->class_loader() == class_loader()))) {
return quicksuperk;
} else {
PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, child_name, loader_data);
@@ -545,7 +542,7 @@
bool calledholdinglock
= ObjectSynchronizer::current_thread_holds_lock((JavaThread*)THREAD, lockObject);
assert(calledholdinglock,"must hold lock for notify");
- assert((!oopDesc::equals(lockObject(), _system_loader_lock_obj) && !is_parallelCapable(lockObject)), "unexpected double_lock_wait");
+ assert((lockObject() != _system_loader_lock_obj && !is_parallelCapable(lockObject)), "unexpected double_lock_wait");
ObjectSynchronizer::notifyall(lockObject, THREAD);
intptr_t recursions = ObjectSynchronizer::complete_exit(lockObject, THREAD);
SystemDictionary_lock->wait();
@@ -853,7 +850,7 @@
// If everything was OK (no exceptions, no null return value), and
// class_loader is NOT the defining loader, do a little more bookkeeping.
if (!HAS_PENDING_EXCEPTION && k != NULL &&
- !oopDesc::equals(k->class_loader(), class_loader())) {
+ k->class_loader() != class_loader()) {
check_constraints(d_hash, k, class_loader, false, THREAD);
@@ -1006,7 +1003,7 @@
if (unsafe_anonymous_host != NULL) {
// Create a new CLD for an unsafe anonymous class, that uses the same class loader
// as the unsafe_anonymous_host
- guarantee(oopDesc::equals(unsafe_anonymous_host->class_loader(), class_loader()), "should be the same");
+ guarantee(unsafe_anonymous_host->class_loader() == class_loader(), "should be the same");
loader_data = ClassLoaderData::unsafe_anonymous_class_loader_data(class_loader);
} else {
loader_data = ClassLoaderData::class_loader_data(class_loader());
@@ -1039,11 +1036,7 @@
// Add to class hierarchy, initialize vtables, and do possible
// deoptimizations.
add_to_hierarchy(k, CHECK_NULL); // No exception, but can block
-
// But, do not add to dictionary.
-
- // compiled code dependencies need to be validated anyway
- notice_modification();
}
// Rewrite and patch constant pool here.
@@ -1212,10 +1205,8 @@
TempNewSymbol pkg_name = NULL;
PackageEntry* pkg_entry = NULL;
ModuleEntry* mod_entry = NULL;
- const char* pkg_string = NULL;
pkg_name = InstanceKlass::package_from_name(class_name, CHECK_false);
if (pkg_name != NULL) {
- pkg_string = pkg_name->as_C_string();
if (loader_data != NULL) {
pkg_entry = loader_data->packages()->lookup_only(pkg_name);
}
@@ -1252,7 +1243,7 @@
// 3. or, the class is from an unamed module
if (!ent->is_modules_image() && ik->is_shared_boot_class()) {
// the class is from the -Xbootclasspath/a
- if (pkg_string == NULL ||
+ if (pkg_name == NULL ||
pkg_entry == NULL ||
pkg_entry->in_unnamed_module()) {
assert(mod_entry == NULL ||
@@ -1264,8 +1255,7 @@
return false;
} else {
bool res = SystemDictionaryShared::is_shared_class_visible_for_classloader(
- ik, class_loader, pkg_string, pkg_name,
- pkg_entry, mod_entry, CHECK_(false));
+ ik, class_loader, pkg_name, pkg_entry, mod_entry, CHECK_(false));
return res;
}
}
@@ -1275,116 +1265,116 @@
Handle protection_domain,
const ClassFileStream *cfs,
TRAPS) {
-
- if (ik != NULL) {
- Symbol* class_name = ik->name();
-
- bool visible = is_shared_class_visible(
- class_name, ik, class_loader, CHECK_NULL);
- if (!visible) {
- return NULL;
- }
-
- // Resolve the superclass and interfaces. They must be the same
- // as in dump time, because the layout of <ik> depends on
- // the specific layout of ik->super() and ik->local_interfaces().
- //
- // If unexpected superclass or interfaces are found, we cannot
- // load <ik> from the shared archive.
+ assert(ik != NULL, "sanity");
+ assert(!ik->is_unshareable_info_restored(), "shared class can be loaded only once");
+ Symbol* class_name = ik->name();
- if (ik->super() != NULL) {
- Symbol* cn = ik->super()->name();
- Klass *s = resolve_super_or_fail(class_name, cn,
- class_loader, protection_domain, true, CHECK_NULL);
- if (s != ik->super()) {
- // The dynamically resolved super class is not the same as the one we used during dump time,
- // so we cannot use ik.
- return NULL;
- } else {
- assert(s->is_shared(), "must be");
- }
- }
+ bool visible = is_shared_class_visible(
+ class_name, ik, class_loader, CHECK_NULL);
+ if (!visible) {
+ return NULL;
+ }
- Array<InstanceKlass*>* interfaces = ik->local_interfaces();
- int num_interfaces = interfaces->length();
- for (int index = 0; index < num_interfaces; index++) {
- InstanceKlass* k = interfaces->at(index);
- Symbol* name = k->name();
- Klass* i = resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_NULL);
- if (k != i) {
- // The dynamically resolved interface class is not the same as the one we used during dump time,
- // so we cannot use ik.
- return NULL;
- } else {
- assert(i->is_shared(), "must be");
- }
- }
-
- InstanceKlass* new_ik = KlassFactory::check_shared_class_file_load_hook(
- ik, class_name, class_loader, protection_domain, cfs, CHECK_NULL);
- if (new_ik != NULL) {
- // The class is changed by CFLH. Return the new class. The shared class is
- // not used.
- return new_ik;
- }
+ // Resolve the superclass and interfaces. They must be the same
+ // as in dump time, because the layout of <ik> depends on
+ // the specific layout of ik->super() and ik->local_interfaces().
+ //
+ // If unexpected superclass or interfaces are found, we cannot
+ // load <ik> from the shared archive.
- // Adjust methods to recover missing data. They need addresses for
- // interpreter entry points and their default native method address
- // must be reset.
-
- // Updating methods must be done under a lock so multiple
- // threads don't update these in parallel
- //
- // Shared classes are all currently loaded by either the bootstrap or
- // internal parallel class loaders, so this will never cause a deadlock
- // on a custom class loader lock.
-
- ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
- {
- HandleMark hm(THREAD);
- Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
- check_loader_lock_contention(lockObject, THREAD);
- ObjectLocker ol(lockObject, THREAD, true);
- // prohibited package check assumes all classes loaded from archive call
- // restore_unshareable_info which calls ik->set_package()
- ik->restore_unshareable_info(loader_data, protection_domain, CHECK_NULL);
+ if (ik->super() != NULL) {
+ Symbol* cn = ik->super()->name();
+ Klass *s = resolve_super_or_fail(class_name, cn,
+ class_loader, protection_domain, true, CHECK_NULL);
+ if (s != ik->super()) {
+ // The dynamically resolved super class is not the same as the one we used during dump time,
+ // so we cannot use ik.
+ return NULL;
+ } else {
+ assert(s->is_shared(), "must be");
}
-
- ik->print_class_load_logging(loader_data, NULL, NULL);
+ }
- // For boot loader, ensure that GetSystemPackage knows that a class in this
- // package was loaded.
- if (class_loader.is_null()) {
- int path_index = ik->shared_classpath_index();
- ResourceMark rm;
- ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
- }
-
- if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
- // Only dump the classes that can be stored into CDS archive
- if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
- ResourceMark rm(THREAD);
- classlist_file->print_cr("%s", ik->name()->as_C_string());
- classlist_file->flush();
- }
- }
-
- // notify a class loaded from shared object
- ClassLoadingService::notify_class_loaded(ik, true /* shared class */);
-
- ik->set_has_passed_fingerprint_check(false);
- if (UseAOT && ik->supers_have_passed_fingerprint_checks()) {
- uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik);
- uint64_t cds_fp = ik->get_stored_fingerprint();
- if (aot_fp != 0 && aot_fp == cds_fp) {
- // This class matches with a class saved in an AOT library
- ik->set_has_passed_fingerprint_check(true);
- } else {
- ResourceMark rm;
- log_info(class, fingerprint)("%s : expected = " PTR64_FORMAT " actual = " PTR64_FORMAT, ik->external_name(), aot_fp, cds_fp);
- }
+ Array<InstanceKlass*>* interfaces = ik->local_interfaces();
+ int num_interfaces = interfaces->length();
+ for (int index = 0; index < num_interfaces; index++) {
+ InstanceKlass* k = interfaces->at(index);
+ Symbol* name = k->name();
+ Klass* i = resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_NULL);
+ if (k != i) {
+ // The dynamically resolved interface class is not the same as the one we used during dump time,
+ // so we cannot use ik.
+ return NULL;
+ } else {
+ assert(i->is_shared(), "must be");
}
}
+
+ InstanceKlass* new_ik = KlassFactory::check_shared_class_file_load_hook(
+ ik, class_name, class_loader, protection_domain, cfs, CHECK_NULL);
+ if (new_ik != NULL) {
+ // The class is changed by CFLH. Return the new class. The shared class is
+ // not used.
+ return new_ik;
+ }
+
+ // Adjust methods to recover missing data. They need addresses for
+ // interpreter entry points and their default native method address
+ // must be reset.
+
+ // Updating methods must be done under a lock so multiple
+ // threads don't update these in parallel
+ //
+ // Shared classes are all currently loaded by either the bootstrap or
+ // internal parallel class loaders, so this will never cause a deadlock
+ // on a custom class loader lock.
+
+ ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
+ {
+ HandleMark hm(THREAD);
+ Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
+ check_loader_lock_contention(lockObject, THREAD);
+ ObjectLocker ol(lockObject, THREAD, true);
+ // prohibited package check assumes all classes loaded from archive call
+ // restore_unshareable_info which calls ik->set_package()
+ ik->restore_unshareable_info(loader_data, protection_domain, CHECK_NULL);
+ }
+
+ ik->print_class_load_logging(loader_data, NULL, NULL);
+
+ // For boot loader, ensure that GetSystemPackage knows that a class in this
+ // package was loaded.
+ if (class_loader.is_null()) {
+ int path_index = ik->shared_classpath_index();
+ ResourceMark rm;
+ ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
+ }
+
+ if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
+ // Only dump the classes that can be stored into CDS archive
+ if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
+ ResourceMark rm(THREAD);
+ classlist_file->print_cr("%s", ik->name()->as_C_string());
+ classlist_file->flush();
+ }
+ }
+
+ // notify a class loaded from shared object
+ ClassLoadingService::notify_class_loaded(ik, true /* shared class */);
+
+ ik->set_has_passed_fingerprint_check(false);
+ if (UseAOT && ik->supers_have_passed_fingerprint_checks()) {
+ uint64_t aot_fp = AOTLoader::get_saved_fingerprint(ik);
+ uint64_t cds_fp = ik->get_stored_fingerprint();
+ if (aot_fp != 0 && aot_fp == cds_fp) {
+ // This class matches with a class saved in an AOT library
+ ik->set_has_passed_fingerprint_check(true);
+ } else {
+ ResourceMark rm;
+ log_info(class, fingerprint)("%s : expected = " PTR64_FORMAT " actual = " PTR64_FORMAT, ik->external_name(), aot_fp, cds_fp);
+ }
+ }
+
return ik;
}
#endif // INCLUDE_CDS
@@ -1439,6 +1429,11 @@
// a named package within the unnamed module. In all cases,
// limit visibility to search for the class only in the boot
// loader's append path.
+ if (!ClassLoader::has_bootclasspath_append()) {
+ // If there is no bootclasspath append entry, no need to continue
+ // searching.
+ return NULL;
+ }
search_only_bootloader_append = true;
}
}
@@ -1736,7 +1731,7 @@
== ObjectSynchronizer::owner_other) {
// contention will likely happen, so increment the corresponding
// contention counter.
- if (oopDesc::equals(loader_lock(), _system_loader_lock_obj)) {
+ if (loader_lock() == _system_loader_lock_obj) {
ClassLoader::sync_systemLoaderLockContentionRate()->inc();
} else {
ClassLoader::sync_nonSystemLoaderLockContentionRate()->inc();
@@ -1849,7 +1844,7 @@
return unloading_occurred;
}
-void SystemDictionary::oops_do(OopClosure* f) {
+void SystemDictionary::oops_do(OopClosure* f, bool include_handles) {
f->do_oop(&_java_system_loader);
f->do_oop(&_java_platform_loader);
f->do_oop(&_system_loader_lock_obj);
@@ -1857,6 +1852,10 @@
// Visit extra methods
invoke_method_table()->oops_do(f);
+
+ if (include_handles) {
+ OopStorageSet::vm_global()->oops_do(f);
+ }
}
// CDS: scan and relocate all classes referenced by _well_known_klasses[].
@@ -1880,7 +1879,6 @@
void SystemDictionary::initialize(TRAPS) {
// Allocate arrays
_placeholders = new PlaceholderTable(_placeholder_table_size);
- _number_of_modifications = 0;
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
@@ -2142,7 +2140,7 @@
// See whether biased locking is enabled and if so set it for this
// klass.
// Note that this must be done past the last potential blocking
- // point / safepoint. We enable biased locking lazily using a
+ // point / safepoint. We might enable biased locking lazily using a
// VM_Operation to iterate the SystemDictionary and installing the
// biasable mark word into each InstanceKlass's prototype header.
// To avoid race conditions where we accidentally miss enabling the
@@ -2154,8 +2152,8 @@
// cleared if revocation occurs too often for this type
// NOTE that we must only do this when the class is initally
// defined, not each time it is referenced from a new class loader
- if (oopDesc::equals(k->class_loader(), class_loader())) {
- k->set_prototype_header(markOopDesc::biased_locking_prototype());
+ if (k->class_loader() == class_loader()) {
+ k->set_prototype_header(markWord::biased_locking_prototype());
}
}
@@ -2164,8 +2162,6 @@
InstanceKlass* sd_check = find_class(d_hash, name, dictionary);
if (sd_check == NULL) {
dictionary->add_klass(d_hash, name, k);
-
- notice_modification();
}
#ifdef ASSERT
sd_check = find_class(d_hash, name, dictionary);
@@ -2349,7 +2345,7 @@
Handle loader1, Handle loader2,
bool is_method, TRAPS) {
// Nothing to do if loaders are the same.
- if (oopDesc::equals(loader1(), loader2())) {
+ if (loader1() == loader2()) {
return NULL;
}
@@ -2861,14 +2857,17 @@
}
TableStatistics SystemDictionary::placeholders_statistics() {
+ MutexLocker ml(SystemDictionary_lock);
return placeholders()->statistics_calculate();
}
TableStatistics SystemDictionary::loader_constraints_statistics() {
+ MutexLocker ml(SystemDictionary_lock);
return constraints()->statistics_calculate();
}
TableStatistics SystemDictionary::protection_domain_cache_statistics() {
+ MutexLocker ml(SystemDictionary_lock);
return pd_cache_table()->statistics_calculate();
}
@@ -2896,15 +2895,3 @@
return 0;
}
}
-
-void SystemDictionary::initialize_oop_storage() {
- _vm_weak_oop_storage =
- new OopStorage("VM Weak Oop Handles",
- VMWeakAlloc_lock,
- VMWeakActive_lock);
-}
-
-OopStorage* SystemDictionary::vm_weak_oop_storage() {
- assert(_vm_weak_oop_storage != NULL, "Uninitialized");
- return _vm_weak_oop_storage;
-}