changeset 8378:77d9c9da7188 jdk8u152-b01

8153134: Infinite loop in handle_wrong_method in jmod Summary: Use Patching_lock to synchronize access between set_code() and clear_code(). Reviewed-by: kvn, dlong
author vkempik
date Mon, 06 Feb 2017 23:36:58 +0300
parents 619700f41f8e
children e765322578aa f89cf87d867d
files src/share/vm/classfile/classLoader.cpp src/share/vm/code/nmethod.cpp src/share/vm/oops/method.cpp src/share/vm/oops/method.hpp
diffstat 4 files changed, 6 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/classLoader.cpp	Thu Feb 02 00:29:28 2017 +0000
+++ b/src/share/vm/classfile/classLoader.cpp	Mon Feb 06 23:36:58 2017 +0300
@@ -1627,7 +1627,6 @@
                 if (nm != NULL && !m->is_method_handle_intrinsic()) {
                   // Throw out the code so that the code cache doesn't fill up
                   nm->make_not_entrant();
-                  m->clear_code();
                 }
                 CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_full_optimization,
                                               methodHandle(), 0, "CTW", THREAD);
@@ -1646,7 +1645,6 @@
             if (nm != NULL && !m->is_method_handle_intrinsic()) {
               // Throw out the code so that the code cache doesn't fill up
               nm->make_not_entrant();
-              m->clear_code();
             }
           }
         }
--- a/src/share/vm/code/nmethod.cpp	Thu Feb 02 00:29:28 2017 +0000
+++ b/src/share/vm/code/nmethod.cpp	Mon Feb 06 23:36:58 2017 +0300
@@ -1506,7 +1506,7 @@
     if (method() != NULL && (method()->code() == this ||
                              method()->from_compiled_entry() == verified_entry_point())) {
       HandleMark hm;
-      method()->clear_code();
+      method()->clear_code(false /* already owns Patching_lock */);
     }
   } // leave critical region under Patching_lock
 
--- a/src/share/vm/oops/method.cpp	Thu Feb 02 00:29:28 2017 +0000
+++ b/src/share/vm/oops/method.cpp	Mon Feb 06 23:36:58 2017 +0300
@@ -98,7 +98,7 @@
   // Fix and bury in Method*
   set_interpreter_entry(NULL); // sets i2i entry and from_int
   set_adapter_entry(NULL);
-  clear_code(); // from_c/from_i get set to c2i/i2i
+  clear_code(false /* don't need a lock */); // from_c/from_i get set to c2i/i2i
 
   if (access_flags.is_native()) {
     clear_native_function();
@@ -846,8 +846,8 @@
 }
 
 // Revert to using the interpreter and clear out the nmethod
-void Method::clear_code() {
-
+void Method::clear_code(bool acquire_lock /* = true */) {
+  MutexLockerEx pl(acquire_lock ? Patching_lock : NULL, Mutex::_no_safepoint_check_flag);
   // this may be NULL if c2i adapters have not been made yet
   // Only should happen at allocate time.
   if (_adapter == NULL) {
@@ -975,6 +975,7 @@
 
 // Install compiled code.  Instantly it can execute.
 void Method::set_code(methodHandle mh, nmethod *code) {
+  MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
   assert( code, "use clear_code to remove code" );
   assert( mh->check_code(), "" );
 
--- a/src/share/vm/oops/method.hpp	Thu Feb 02 00:29:28 2017 +0000
+++ b/src/share/vm/oops/method.hpp	Mon Feb 06 23:36:58 2017 +0300
@@ -445,7 +445,7 @@
   address verified_code_entry();
   bool check_code() const;      // Not inline to avoid circular ref
   nmethod* volatile code() const                 { assert( check_code(), "" ); return (nmethod *)OrderAccess::load_ptr_acquire(&_code); }
-  void clear_code();            // Clear out any compiled code
+  void clear_code(bool acquire_lock = true);            // Clear out any compiled code
   static void set_code(methodHandle mh, nmethod* code);
   void set_adapter_entry(AdapterHandlerEntry* adapter) {  _adapter = adapter; }
   address get_i2c_entry();