changeset 23426:682119c4c32e

8058737: CodeCache::find_blob fails with 'unsafe access to zombie method' Summary: Remove active ICStubs from zombie nmethods Reviewed-by: kvn, iveresov
author thartmann
date Thu, 08 Oct 2015 09:37:23 +0200
parents aa97f9321b9c
children c1950f51ed60
files src/share/vm/code/compiledIC.cpp src/share/vm/code/compiledIC.hpp src/share/vm/code/nmethod.cpp src/share/vm/code/nmethod.hpp src/share/vm/runtime/sweeper.cpp
diffstat 5 files changed, 27 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/code/compiledIC.cpp	Tue Oct 06 12:18:17 2015 +0200
+++ b/src/share/vm/code/compiledIC.cpp	Thu Oct 08 09:37:23 2015 +0200
@@ -155,6 +155,14 @@
   return _ic_call->destination();
 }
 
+// Clears the IC stub if the compiled IC is in transition state
+void CompiledIC::clear_ic_stub() {
+  if (is_in_transition_state()) {
+    ICStub* stub = ICStub_from_destination_address(stub_address());
+    stub->clear();
+  }
+}
+
 
 //-----------------------------------------------------------------------------
 // High-level access to an inline cache. Guaranteed to be MT-safe.
@@ -333,10 +341,7 @@
 
   if (safe_transition) {
     // Kill any leftover stub we might have too
-    if (is_in_transition_state()) {
-      ICStub* old_stub = ICStub_from_destination_address(stub_address());
-      old_stub->clear();
-    }
+    clear_ic_stub();
     if (is_optimized()) {
     set_ic_destination(entry);
   } else {
--- a/src/share/vm/code/compiledIC.hpp	Tue Oct 06 12:18:17 2015 +0200
+++ b/src/share/vm/code/compiledIC.hpp	Thu Oct 08 09:37:23 2015 +0200
@@ -230,6 +230,7 @@
   //
   void set_to_clean();  // Can only be called during a safepoint operation
   void set_to_monomorphic(CompiledICInfo& info);
+  void clear_ic_stub();
 
   // Returns true if successful and false otherwise. The call can fail if memory
   // allocation in the code cache fails.
--- a/src/share/vm/code/nmethod.cpp	Tue Oct 06 12:18:17 2015 +0200
+++ b/src/share/vm/code/nmethod.cpp	Thu Oct 08 09:37:23 2015 +0200
@@ -1148,6 +1148,18 @@
   }
 }
 
+// Clear ICStubs of all compiled ICs
+void nmethod::clear_ic_stubs() {
+  assert_locked_or_safepoint(CompiledIC_lock);
+  RelocIterator iter(this);
+  while(iter.next()) {
+    if (iter.type() == relocInfo::virtual_call_type) {
+      CompiledIC* ic = CompiledIC_at(&iter);
+      ic->clear_ic_stub();
+    }
+  }
+}
+
 
 void nmethod::cleanup_inline_caches() {
 
--- a/src/share/vm/code/nmethod.hpp	Tue Oct 06 12:18:17 2015 +0200
+++ b/src/share/vm/code/nmethod.hpp	Thu Oct 08 09:37:23 2015 +0200
@@ -577,6 +577,7 @@
 
   // Inline cache support
   void clear_inline_caches();
+  void clear_ic_stubs();
   void cleanup_inline_caches();
   bool inlinecache_check_contains(address addr) const {
     return (addr >= code_begin() && addr < verified_entry_point());
--- a/src/share/vm/runtime/sweeper.cpp	Tue Oct 06 12:18:17 2015 +0200
+++ b/src/share/vm/runtime/sweeper.cpp	Thu Oct 08 09:37:23 2015 +0200
@@ -542,6 +542,10 @@
       if (PrintMethodFlushing && Verbose) {
         tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm);
       }
+      // Clear ICStubs to prevent back patching stubs of zombie or unloaded
+      // nmethods during the next safepoint (see ICStub::finalize).
+      MutexLocker cl(CompiledIC_lock);
+      nm->clear_ic_stubs();
       // Code cache state change is tracked in make_zombie()
       nm->make_zombie();
       _zombified_count++;