diff -r 4645b6d57f54 -r 9b70ebd131b4 src/hotspot/share/oops/method.cpp --- a/src/hotspot/share/oops/method.cpp Thu May 23 09:46:49 2019 +0200 +++ b/src/hotspot/share/oops/method.cpp Thu May 23 10:13:29 2019 +0200 @@ -103,7 +103,7 @@ // Fix and bury in Method* set_interpreter_entry(NULL); // sets i2i entry and from_int set_adapter_entry(NULL); - clear_code(false /* don't need a lock */); // from_c/from_i get set to c2i/i2i + Method::clear_code(); // from_c/from_i get set to c2i/i2i if (access_flags.is_native()) { clear_native_function(); @@ -815,7 +815,7 @@ set_native_function( SharedRuntime::native_method_throw_unsatisfied_link_error_entry(), !native_bind_event_is_interesting); - clear_code(); + this->unlink_code(); } address Method::critical_native_function() { @@ -938,8 +938,7 @@ } // Revert to using the interpreter and clear out the nmethod -void Method::clear_code(bool acquire_lock /* = true */) { - MutexLocker pl(acquire_lock ? Patching_lock : NULL, Mutex::_no_safepoint_check_flag); +void Method::clear_code() { // this may be NULL if c2i adapters have not been made yet // Only should happen at allocate time. if (adapter() == NULL) { @@ -953,6 +952,25 @@ _code = NULL; } +void Method::unlink_code(CompiledMethod *compare) { + MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock, Mutex::_no_safepoint_check_flag); + // We need to check if either the _code or _from_compiled_code_entry_point + // refer to this nmethod because there is a race in setting these two fields + // in Method* as seen in bugid 4947125. + // If the vep() points to the zombie nmethod, the memory for the nmethod + // could be flushed and the compiler and vtable stubs could still call + // through it. + if (code() == compare || + from_compiled_entry() == compare->verified_entry_point()) { + clear_code(); + } +} + +void Method::unlink_code() { + MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock, Mutex::_no_safepoint_check_flag); + clear_code(); +} + #if INCLUDE_CDS // Called by class data sharing to remove any entry points (which are not shared) void Method::unlink_method() { @@ -1179,7 +1197,7 @@ // Install compiled code. Instantly it can execute. void Method::set_code(const methodHandle& mh, CompiledMethod *code) { - MutexLocker pl(Patching_lock, Mutex::_no_safepoint_check_flag); + MutexLocker pl(CompiledMethod_lock, Mutex::_no_safepoint_check_flag); assert( code, "use clear_code to remove code" ); assert( mh->check_code(), "" );