< prev index next >

src/hotspot/share/oops/method.cpp

Print this page
rev 54838 : [mq]: 8221734-v2
rev 54839 : [mq]: 8221734-v3

@@ -813,11 +813,11 @@
 void Method::clear_native_function() {
   // Note: is_method_handle_intrinsic() is allowed here.
   set_native_function(
     SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
     !native_bind_event_is_interesting);
-  Method::unlink_code(this);
+  this->unlink_code();
 }
 
 address Method::critical_native_function() {
   methodHandle mh(this);
   return NativeLookup::lookup_critical_entry(mh);

@@ -950,26 +950,27 @@
   _from_interpreted_entry = _i2i_entry;
   OrderAccess::storestore();
   _code = NULL;
 }
 
-void Method::unlink_code(Method *method, CompiledMethod *compare) {
-  if (method == NULL) {
-    return;
-  }
+void Method::unlink_code(CompiledMethod *compare) {
   MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
-  if (method->code() == compare ||
-      method->from_compiled_entry() == compare->verified_entry_point()) {
-    method->clear_code();
+  // We need to check if both the _code and _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(Method *method) {
-  if (method != NULL) {
+void Method::unlink_code() {
     MutexLocker ml(CompiledMethod_lock->owned_by_self() ? NULL : CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
-    method->clear_code();
-  }
+  clear_code();
 }
 
 #if INCLUDE_CDS
 // Called by class data sharing to remove any entry points (which are not shared)
 void Method::unlink_method() {
< prev index next >