# HG changeset patch # User thartmann # Date 1459833584 -7200 # Node ID a31d47bbbdf635687a69b68215a742738a10abd0 # Parent c2660335bf81c68b62d1b0f62e5e3af6b74a6846 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 diff -r c2660335bf81 -r a31d47bbbdf6 hotspot/src/share/vm/runtime/thread.cpp --- 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*)) { diff -r c2660335bf81 -r a31d47bbbdf6 hotspot/src/share/vm/runtime/thread.hpp --- 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.