From 985d50e207ec713a1f26c84e1f4bcc7236be0117 Mon Sep 17 00:00:00 2001 From: vkempik Date: Mon, 6 Feb 2017 23:36:58 +0300 Subject: [PATCH] 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 --- src/share/vm/classfile/classLoader.cpp | 2 -- src/share/vm/code/nmethod.cpp | 2 +- src/share/vm/oops/method.cpp | 7 ++++--- src/share/vm/oops/method.hpp | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/share/vm/classfile/classLoader.cpp b/src/share/vm/classfile/classLoader.cpp index ef5766e18..a33263b0f 100644 --- a/src/share/vm/classfile/classLoader.cpp +++ b/src/share/vm/classfile/classLoader.cpp @@ -1627,7 +1627,6 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { 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 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { 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(); } } } diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp index d1cbdccb0..e88ce9775 100644 --- a/src/share/vm/code/nmethod.cpp +++ b/src/share/vm/code/nmethod.cpp @@ -1506,7 +1506,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) { 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 diff --git a/src/share/vm/oops/method.cpp b/src/share/vm/oops/method.cpp index b0d4950b1..35d55087c 100644 --- a/src/share/vm/oops/method.cpp +++ b/src/share/vm/oops/method.cpp @@ -98,7 +98,7 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, int size) { // 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 @@ void Method::set_not_osr_compilable(int comp_level, bool report, const char* rea } // 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 @@ bool Method::check_code() const { // 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(), "" ); diff --git a/src/share/vm/oops/method.hpp b/src/share/vm/oops/method.hpp index 5eeeaa117..90b7029e9 100644 --- a/src/share/vm/oops/method.hpp +++ b/src/share/vm/oops/method.hpp @@ -445,7 +445,7 @@ class Method : public Metadata { 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(); -- GitLab