7024970: 2/3 assert(ServiceThread::is_service_thread(Thread::current())) failed: Service thread must post enqueue

Change nmethod_lock() to also prevent zombification of the nmethod. CompiledMethodUnload events also need to lock the nmethod. Clean ups in nmethod::make_not_entrant_or_zombie()

Reviewed-by: dholmes, kamg, never, dsamersoff, ysr, coleenp, acorn
This commit is contained in:
Daniel D. Daugherty 2011-03-15 06:37:31 -07:00
parent 0c3498d374
commit c4e301bffa
4 changed files with 52 additions and 26 deletions

View file

@ -194,7 +194,10 @@ class nmethod : public CodeBlob {
NOT_PRODUCT(bool _has_debug_info; )
// Nmethod Flushing lock (if non-zero, then the nmethod is not removed)
// Nmethod Flushing lock. If non-zero, then the nmethod is not removed
// and is not made into a zombie. However, once the nmethod is made into
// a zombie, it will be locked one final time if CompiledMethodUnload
// event processing needs to be done.
jint _lock_count;
// not_entrant method removal. Each mark_sweep pass will update
@ -522,8 +525,9 @@ public:
void flush();
public:
// If returning true, it is unsafe to remove this nmethod even though it is a zombie
// nmethod, since the VM might have a reference to it. Should only be called from a safepoint.
// When true is returned, it is unsafe to remove this nmethod even if
// it is a zombie, since the VM or the ServiceThread might still be
// using it.
bool is_locked_by_vm() const { return _lock_count >0; }
// See comment at definition of _last_seen_on_stack
@ -689,13 +693,20 @@ public:
};
// Locks an nmethod so its code will not get removed, even if it is a zombie/not_entrant method
// Locks an nmethod so its code will not get removed and it will not
// be made into a zombie, even if it is a not_entrant method. After the
// nmethod becomes a zombie, if CompiledMethodUnload event processing
// needs to be done, then lock_nmethod() is used directly to keep the
// generated code from being reused too early.
class nmethodLocker : public StackObj {
nmethod* _nm;
public:
static void lock_nmethod(nmethod* nm); // note: nm can be NULL
// note: nm can be NULL
// Only JvmtiDeferredEvent::compiled_method_unload_event()
// should pass zombie_ok == true.
static void lock_nmethod(nmethod* nm, bool zombie_ok = false);
static void unlock_nmethod(nmethod* nm); // (ditto)
nmethodLocker(address pc); // derive nm from pc