8074553: Crash with assert(!is_unloaded()) failed: should not call follow on unloaded nmethod
authorthartmann
Tue, 05 Apr 2016 07:19:44 +0200
changeset 37288 a31d47bbbdf6
parent 37287 c2660335bf81
child 37290 8604d4659cee
8074553: Crash with assert(!is_unloaded()) failed: should not call follow on unloaded nmethod Summary: Sweeper thread needs to override nmethods_do() to prevent G1 from unloading _scanned_nmethod. Reviewed-by: kvn, mgerdin
hotspot/src/share/vm/runtime/thread.cpp
hotspot/src/share/vm/runtime/thread.hpp
--- a/hotspot/src/share/vm/runtime/thread.cpp	Mon Apr 04 12:52:11 2016 +0200
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Tue Apr 05 07:19:44 2016 +0200
@@ -791,10 +791,6 @@
   handle_area()->oops_do(f);
 }
 
-void Thread::nmethods_do(CodeBlobClosure* cf) {
-  // no nmethods in a generic thread...
-}
-
 void Thread::metadata_handles_do(void f(Metadata*)) {
   // Only walk the Handles in Thread.
   if (metadata_handles() != NULL) {
@@ -2827,8 +2823,6 @@
 }
 
 void JavaThread::nmethods_do(CodeBlobClosure* cf) {
-  Thread::nmethods_do(cf);  // (super method is a no-op)
-
   assert((!has_last_Java_frame() && java_call_counter() == 0) ||
          (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
 
@@ -3301,6 +3295,7 @@
 : JavaThread(&sweeper_thread_entry) {
   _scanned_nmethod = NULL;
 }
+
 void CodeCacheSweeperThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   JavaThread::oops_do(f, cld_f, cf);
   if (_scanned_nmethod != NULL && cf != NULL) {
@@ -3311,6 +3306,16 @@
   }
 }
 
+void CodeCacheSweeperThread::nmethods_do(CodeBlobClosure* cf) {
+  JavaThread::nmethods_do(cf);
+  if (_scanned_nmethod != NULL && cf != NULL) {
+    // Safepoints can occur when the sweeper is scanning an nmethod so
+    // process it here to make sure it isn't unloaded in the middle of
+    // a scan.
+    cf->do_code_blob(_scanned_nmethod);
+  }
+}
+
 
 // ======= Threads ========
 
@@ -4348,9 +4353,13 @@
 
 void Threads::nmethods_do(CodeBlobClosure* cf) {
   ALL_JAVA_THREADS(p) {
-    p->nmethods_do(cf);
-  }
-  VMThread::vm_thread()->nmethods_do(cf);
+    // This is used by the code cache sweeper to mark nmethods that are active
+    // on the stack of a Java thread. Ignore the sweeper thread itself to avoid
+    // marking CodeCacheSweeperThread::_scanned_nmethod as active.
+    if(!p->is_Code_cache_sweeper_thread()) {
+      p->nmethods_do(cf);
+    }
+  }
 }
 
 void Threads::metadata_do(void f(Metadata*)) {
--- a/hotspot/src/share/vm/runtime/thread.hpp	Mon Apr 04 12:52:11 2016 +0200
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Tue Apr 05 07:19:44 2016 +0200
@@ -509,9 +509,6 @@
     }
   }
 
-  // Sweeper support
-  void nmethods_do(CodeBlobClosure* cf);
-
   // jvmtiRedefineClasses support
   void metadata_handles_do(void f(Metadata*));
 
@@ -1649,7 +1646,7 @@
   void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
 
   // Sweeper operations
-  void nmethods_do(CodeBlobClosure* cf);
+  virtual void nmethods_do(CodeBlobClosure* cf);
 
   // RedefineClasses Support
   void metadata_do(void f(Metadata*));
@@ -1997,10 +1994,10 @@
   bool is_hidden_from_external_view() const { return true; }
 
   bool is_Code_cache_sweeper_thread() const { return true; }
-  // GC support
-  // Apply "f->do_oop" to all root oops in "this".
-  // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames
+
+  // Prevent GC from unloading _scanned_nmethod
   void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
+  void nmethods_do(CodeBlobClosure* cf);
 };
 
 // A thread used for Compilation.