src/hotspot/share/code/nmethod.cpp
changeset 52385 5c679ec60888
parent 52384 d6dc479bcdd3
child 52405 c0c6cdea32f1
--- a/src/hotspot/share/code/nmethod.cpp	Thu Nov 01 14:57:26 2018 +0100
+++ b/src/hotspot/share/code/nmethod.cpp	Fri Nov 02 08:33:59 2018 +0100
@@ -413,7 +413,6 @@
   _oops_do_mark_link       = NULL;
   _jmethod_id              = NULL;
   _osr_link                = NULL;
-  _unloading_next          = NULL;
   _scavenge_root_link      = NULL;
   _scavenge_root_state     = 0;
 #if INCLUDE_RTM_OPT
@@ -599,6 +598,7 @@
 
     code_buffer->copy_code_and_locs_to(this);
     code_buffer->copy_values_to(this);
+
     if (ScavengeRootsInCode) {
       Universe::heap()->register_nmethod(this);
     }
@@ -757,6 +757,7 @@
     code_buffer->copy_values_to(this);
     debug_info->copy_to(this);
     dependencies->copy_to(this);
+    clear_unloading_state();
     if (ScavengeRootsInCode) {
       Universe::heap()->register_nmethod(this);
     }
@@ -1025,8 +1026,7 @@
   mdo->inc_decompile_count();
 }
 
-void nmethod::make_unloaded(oop cause) {
-
+void nmethod::make_unloaded() {
   post_compiled_method_unload();
 
   // This nmethod is being unloaded, make sure that dependencies
@@ -1042,11 +1042,8 @@
     LogStream ls(lt);
     ls.print("making nmethod " INTPTR_FORMAT
              " unloadable, Method*(" INTPTR_FORMAT
-             "), cause(" INTPTR_FORMAT ") ",
-             p2i(this), p2i(_method), p2i(cause));
-     if (cause != NULL) {
-       cause->print_value_on(&ls);
-     }
+             ") ",
+             p2i(this), p2i(_method));
      ls.cr();
   }
   // Unlink the osr method, so we do not look this up again
@@ -1079,12 +1076,6 @@
 
   // Make the class unloaded - i.e., change state and notify sweeper
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  if (is_in_use()) {
-    // Transitioning directly from live to unloaded -- so
-    // we need to force a cache clean-up; remember this
-    // for later on.
-    CodeCache::set_needs_cache_clean(true);
-  }
 
   // Unregister must be done before the state change
   Universe::heap()->unregister_nmethod(this);
@@ -1092,7 +1083,7 @@
   _state = unloaded;
 
   // Log the unloading.
-  log_state_change(cause);
+  log_state_change();
 
 #if INCLUDE_JVMCI
   // The method can only be unloaded after the pointer to the installed code
@@ -1116,7 +1107,7 @@
   }
 }
 
-void nmethod::log_state_change(oop cause) const {
+void nmethod::log_state_change() const {
   if (LogCompilation) {
     if (xtty != NULL) {
       ttyLocker ttyl;  // keep the following output all in one block
@@ -1129,9 +1120,6 @@
                          (_state == zombie ? " zombie='1'" : ""));
       }
       log_identity(xtty);
-      if (cause != NULL) {
-        xtty->print(" cause='%s'", cause->klass()->external_name());
-      }
       xtty->stamp();
       xtty->end_elem();
     }
@@ -1380,21 +1368,6 @@
   }
 }
 
-
-// If this oop is not live, the nmethod can be unloaded.
-bool nmethod::can_unload(BoolObjectClosure* is_alive, oop* root) {
-  assert(root != NULL, "just checking");
-  oop obj = *root;
-  if (obj == NULL || is_alive->do_object_b(obj)) {
-      return false;
-  }
-
-  // An nmethod might be unloaded simply because one of its constant oops has gone dead.
-  // No actual classes need to be unloaded in order for this to occur.
-  make_unloaded(obj);
-  return true;
-}
-
 // ------------------------------------------------------------------
 // post_compiled_method_load_event
 // new method for install_code() path
@@ -1468,70 +1441,6 @@
   set_unload_reported();
 }
 
-bool nmethod::unload_if_dead_at(RelocIterator* iter_at_oop, BoolObjectClosure *is_alive) {
-  assert(iter_at_oop->type() == relocInfo::oop_type, "Wrong relocation type");
-
-  oop_Relocation* r = iter_at_oop->oop_reloc();
-  // Traverse those oops directly embedded in the code.
-  // Other oops (oop_index>0) are seen as part of scopes_oops.
-  assert(1 == (r->oop_is_immediate()) +
-         (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()),
-         "oop must be found in exactly one place");
-  if (r->oop_is_immediate() && r->oop_value() != NULL) {
-    // Unload this nmethod if the oop is dead.
-    if (can_unload(is_alive, r->oop_addr())) {
-      return true;;
-    }
-  }
-
-  return false;
-}
-
-bool nmethod::do_unloading_scopes(BoolObjectClosure* is_alive) {
-  // Scopes
-  for (oop* p = oops_begin(); p < oops_end(); p++) {
-    if (*p == Universe::non_oop_word())  continue;  // skip non-oops
-    if (can_unload(is_alive, p)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool nmethod::do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive) {
-  // Compiled code
-
-  // Prevent extra code cache walk for platforms that don't have immediate oops.
-  if (relocInfo::mustIterateImmediateOopsInCode()) {
-    RelocIterator iter(this, low_boundary);
-    while (iter.next()) {
-      if (iter.type() == relocInfo::oop_type) {
-        if (unload_if_dead_at(&iter, is_alive)) {
-          return true;
-        }
-      }
-    }
-  }
-
-  return do_unloading_scopes(is_alive);
-}
-
-#if INCLUDE_JVMCI
-bool nmethod::do_unloading_jvmci() {
-  if (_jvmci_installed_code != NULL) {
-    if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
-      if (_jvmci_installed_code_triggers_invalidation) {
-        // The reference to the installed code has been dropped so invalidate
-        // this nmethod and allow the sweeper to reclaim it.
-        make_not_entrant();
-      }
-      clear_jvmci_installed_code();
-    }
-  }
-  return false;
-}
-#endif
-
 // Iterate over metadata calling this function.   Used by RedefineClasses
 void nmethod::metadata_do(void f(Metadata*)) {
   {
@@ -1579,6 +1488,34 @@
   if (_method != NULL) f(_method);
 }
 
+
+// This is called at the end of the strong tracing/marking phase of a
+// GC to unload an nmethod if it contains otherwise unreachable
+// oops.
+
+void nmethod::do_unloading(bool unloading_occurred) {
+  // Make sure the oop's ready to receive visitors
+  assert(!is_zombie() && !is_unloaded(),
+         "should not call follow on zombie or unloaded nmethod");
+
+  if (is_unloading()) {
+    make_unloaded();
+  } else {
+#if INCLUDE_JVMCI
+    if (_jvmci_installed_code != NULL) {
+      if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
+        if (_jvmci_installed_code_triggers_invalidation) {
+          make_not_entrant();
+        }
+        clear_jvmci_installed_code();
+      }
+    }
+#endif
+
+    unload_nmethod_caches(unloading_occurred);
+  }
+}
+
 void nmethod::oops_do(OopClosure* f, bool allow_zombie) {
   // make sure the oops ready to receive visitors
   assert(allow_zombie || !is_zombie(), "should not call follow on zombie nmethod");