src/hotspot/share/oops/klass.cpp
changeset 52311 274ba8fbd96d
parent 52062 8dbf1a13af49
child 52356 19c4a3eec4d7
--- a/src/hotspot/share/oops/klass.cpp	Mon Oct 29 08:38:59 2018 -0400
+++ b/src/hotspot/share/oops/klass.cpp	Mon Oct 29 10:21:34 2018 -0400
@@ -117,7 +117,7 @@
   Klass *r = this;
   while( r->is_abstract() ) {   // Receiver is abstract?
     Klass *s = r->subklass();   // Check for exactly 1 subklass
-    if( !s || s->next_sibling() ) // Oops; wrong count; give up
+    if (s == NULL || s->next_sibling() != NULL) // Oops; wrong count; give up
       return this;              // Return 'this' as a no-progress flag
     r = s;                    // Loop till find concrete class
   }
@@ -358,11 +358,49 @@
 }
 
 
+// superklass links
 InstanceKlass* Klass::superklass() const {
   assert(super() == NULL || super()->is_instance_klass(), "must be instance klass");
   return _super == NULL ? NULL : InstanceKlass::cast(_super);
 }
 
+// subklass links.  Used by the compiler (and vtable initialization)
+// May be cleaned concurrently, so must use the Compile_lock.
+// The log parameter is for clean_weak_klass_links to report unlinked classes.
+Klass* Klass::subklass(bool log) const {
+  assert_locked_or_safepoint(Compile_lock);
+  for (Klass* chain = _subklass; chain != NULL;
+       chain = chain->_next_sibling) {
+    if (chain->is_loader_alive()) {
+      return chain;
+    } else if (log) {
+      if (log_is_enabled(Trace, class, unload)) {
+        ResourceMark rm;
+        log_trace(class, unload)("unlinking class (subclass): %s", chain->external_name());
+      }
+    }
+  }
+  return NULL;
+}
+
+Klass* Klass::next_sibling(bool log) const {
+  assert_locked_or_safepoint(Compile_lock);
+  for (Klass* chain = _next_sibling; chain != NULL;
+       chain = chain->_next_sibling) {
+    // Only return alive klass, there may be stale klass
+    // in this chain if cleaned concurrently.
+    if (chain->is_loader_alive()) {
+      return chain;
+    } else if (log) {
+      if (log_is_enabled(Trace, class, unload)) {
+        ResourceMark rm;
+        log_trace(class, unload)("unlinking class (sibling): %s", chain->external_name());
+      }
+    }
+  }
+  return NULL;
+}
+
 void Klass::set_subklass(Klass* s) {
   assert(s != this, "sanity check");
   _subklass = s;
@@ -374,6 +412,7 @@
 }
 
 void Klass::append_to_sibling_list() {
+  assert_locked_or_safepoint(Compile_lock);
   debug_only(verify();)
   // add ourselves to superklass' subklass list
   InstanceKlass* super = superklass();
@@ -381,6 +420,7 @@
   assert((!super->is_interface()    // interfaces cannot be supers
           && (super->superklass() == NULL || !is_interface())),
          "an interface can only be a subklass of Object");
+
   Klass* prev_first_subklass = super->subklass();
   if (prev_first_subklass != NULL) {
     // set our sibling to be the superklass' previous first subklass
@@ -396,6 +436,7 @@
 }
 
 void Klass::clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses) {
+  assert_locked_or_safepoint(Compile_lock);
   if (!ClassUnloading || !unloading_occurred) {
     return;
   }
@@ -410,30 +451,14 @@
     assert(current->is_loader_alive(), "just checking, this should be live");
 
     // Find and set the first alive subklass
-    Klass* sub = current->subklass();
-    while (sub != NULL && !sub->is_loader_alive()) {
-#ifndef PRODUCT
-      if (log_is_enabled(Trace, class, unload)) {
-        ResourceMark rm;
-        log_trace(class, unload)("unlinking class (subclass): %s", sub->external_name());
-      }
-#endif
-      sub = sub->next_sibling();
-    }
+    Klass* sub = current->subklass(true);
     current->set_subklass(sub);
     if (sub != NULL) {
       stack.push(sub);
     }
 
     // Find and set the first alive sibling
-    Klass* sibling = current->next_sibling();
-    while (sibling != NULL && !sibling->is_loader_alive()) {
-      if (log_is_enabled(Trace, class, unload)) {
-        ResourceMark rm;
-        log_trace(class, unload)("[Unlinking class (sibling) %s]", sibling->external_name());
-      }
-      sibling = sibling->next_sibling();
-    }
+    Klass* sibling = current->next_sibling(true);
     current->set_next_sibling(sibling);
     if (sibling != NULL) {
       stack.push(sibling);