--- old/src/share/vm/classfile/classLoaderData.cpp 2016-12-21 08:13:50.567595694 -0500 +++ new/src/share/vm/classfile/classLoaderData.cpp 2016-12-21 08:13:49.512884288 -0500 @@ -205,12 +205,13 @@ } void ClassLoaderData::modules_do(void f(ModuleEntry*)) { - assert_locked_or_safepoint(Module_lock); - if (_modules != NULL) { - for (int i = 0; i < _modules->table_size(); i++) { - for (ModuleEntry* entry = _modules->bucket(i); - entry != NULL; - entry = entry->next()) { + // Lock-free access requires load_ptr_acquire + ModuleEntryTable* modules = load_ptr_acquire(&_modules); + if (modules != NULL) { + for (int i = 0; i < modules->table_size(); i++) { + for (ModuleEntry* entry = modules->bucket(i); + entry != NULL; + entry = entry->next()) { f(entry); } } @@ -223,8 +224,8 @@ if (packages != NULL) { for (int i = 0; i < packages->table_size(); i++) { for (PackageEntry* entry = packages->bucket(i); - entry != NULL; - entry = entry->next()) { + entry != NULL; + entry = entry->next()) { f(entry); } } --- old/src/share/vm/classfile/moduleEntry.cpp 2016-12-21 08:13:53.924498638 -0500 +++ new/src/share/vm/classfile/moduleEntry.cpp 2016-12-21 08:13:52.882463414 -0500 @@ -167,7 +167,6 @@ } bool ModuleEntry::has_reads() const { - assert_locked_or_safepoint(Module_lock); return ((_reads != NULL) && !_reads->is_empty()); } @@ -202,9 +201,7 @@ } void ModuleEntry::module_reads_do(ModuleClosure* const f) { - assert_locked_or_safepoint(Module_lock); assert(f != NULL, "invariant"); - if (has_reads()) { int reads_len = _reads->length(); for (int i = 0; i < reads_len; ++i) { @@ -225,7 +222,7 @@ } ModuleEntryTable::~ModuleEntryTable() { - assert_locked_or_safepoint(Module_lock); + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); // Walk through all buckets and all entries in each bucket, // freeing each entry. --- old/src/share/vm/classfile/packageEntry.cpp 2016-12-21 08:13:57.283947713 -0500 +++ new/src/share/vm/classfile/packageEntry.cpp 2016-12-21 08:13:56.229596439 -0500 @@ -98,17 +98,9 @@ } if (m == NULL) { - // NULL indicates the package is being unqualifiedly exported - if (has_qual_exports_list()) { - // Legit to transition a package from being qualifiedly exported - // to unqualified. Clean up the qualified lists at the next - // safepoint. - _exported_pending_delete = _qualified_exports; - } - - // Mark package as unqualifiedly exported + // NULL indicates the package is being unqualifiedly exported. Clean up + // the qualified list at the next safepoint. set_unqual_exported(); - } else { // Add the exported module add_qexport(m); @@ -160,18 +152,9 @@ void PackageEntry::delete_qualified_exports() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - if (_exported_pending_delete != NULL) { - // If a transition occurred from qualified to unqualified, the _qualified_exports - // field should have been NULL'ed out. - assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active"); - delete _exported_pending_delete; - } - if (_qualified_exports != NULL) { delete _qualified_exports; } - - _exported_pending_delete = NULL; _qualified_exports = NULL; } @@ -181,7 +164,7 @@ } PackageEntryTable::~PackageEntryTable() { - assert_locked_or_safepoint(Module_lock); + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); // Walk through all buckets and all entries in each bucket, // freeing each entry. @@ -302,12 +285,9 @@ // iteration of qualified exports void PackageEntry::package_exports_do(ModuleClosure* const f) { - assert_locked_or_safepoint(Module_lock); assert(f != NULL, "invariant"); - if (has_qual_exports_list()) { int qe_len = _qualified_exports->length(); - for (int i = 0; i < qe_len; ++i) { f->do_module(_qualified_exports->at(i)); } --- old/src/share/vm/classfile/packageEntry.hpp 2016-12-21 08:14:00.565631527 -0500 +++ new/src/share/vm/classfile/packageEntry.hpp 2016-12-21 08:13:59.522757025 -0500 @@ -70,7 +70,6 @@ bool _is_exported_unqualified; bool _is_exported_allUnnamed; bool _must_walk_exports; - GrowableArray* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint GrowableArray* _qualified_exports; TRACE_DEFINE_TRACE_ID_FIELD; @@ -84,7 +83,6 @@ _is_exported_unqualified = false; _is_exported_allUnnamed = false; _must_walk_exports = false; - _exported_pending_delete = NULL; _qualified_exports = NULL; } @@ -106,29 +104,20 @@ } // Returns true if there are any explicit qualified exports bool has_qual_exports_list() const { - assert(!(_qualified_exports != NULL && _is_exported_unqualified), - "_qualified_exports set at same time as _is_exported_unqualified"); - return (_qualified_exports != NULL); + return (!is_unqual_exported() && _qualified_exports != NULL); } bool is_exported_allUnnamed() const { - assert(!(_is_exported_allUnnamed && _is_exported_unqualified), - "_is_exported_allUnnamed set at same time as _is_exported_unqualified"); - return _is_exported_allUnnamed; + return (!is_unqual_exported() && _is_exported_allUnnamed); } bool is_unqual_exported() const { - assert(!(_qualified_exports != NULL && _is_exported_unqualified), - "_qualified_exports set at same time as _is_exported_unqualified"); - assert(!(_is_exported_allUnnamed && _is_exported_unqualified), - "_is_exported_allUnnamed set at same time as _is_exported_unqualified"); return _is_exported_unqualified; } void set_unqual_exported() { assert(Module_lock->owned_by_self(), "should have the Module_lock"); _is_exported_unqualified = true; _is_exported_allUnnamed = false; - _qualified_exports = NULL; } - bool exported_pending_delete() const { return (_exported_pending_delete != NULL); } + bool exported_pending_delete() const { return (is_unqual_exported() && _qualified_exports != NULL); } void set_exported(ModuleEntry* m);