--- old/src/share/vm/code/codeCache.cpp 2015-08-27 08:36:38.854134395 +0200 +++ new/src/share/vm/code/codeCache.cpp 2015-08-27 08:36:38.782134393 +0200 @@ -746,17 +746,14 @@ void CodeCache::gc_epilogue() { assert_locked_or_safepoint(CodeCache_lock); NMethodIterator iter; - while(iter.next()) { + while(iter.next_alive()) { nmethod* nm = iter.method(); - if (!nm->is_zombie()) { - if (needs_cache_clean()) { - // Clean ICs of unloaded nmethods as well because they may reference other - // unloaded nmethods that may be flushed earlier in the sweeper cycle. - nm->cleanup_inline_caches(); - } - DEBUG_ONLY(nm->verify()); - DEBUG_ONLY(nm->verify_oop_relocations()); + assert(!nm->is_unloaded(), "Tautology"); + if (needs_cache_clean()) { + nm->cleanup_inline_caches(); } + DEBUG_ONLY(nm->verify()); + DEBUG_ONLY(nm->verify_oop_relocations()); } set_needs_cache_clean(false); prune_scavenge_root_nmethods(); --- old/src/share/vm/code/compiledIC.cpp 2015-08-27 08:36:39.150134403 +0200 +++ new/src/share/vm/code/compiledIC.cpp 2015-08-27 08:36:39.078134401 +0200 @@ -287,6 +287,7 @@ assert( is_c1_method || !is_monomorphic || is_optimized() || + !caller->is_alive() || (cached_metadata() != NULL && cached_metadata()->is_klass()), "sanity check"); #endif // ASSERT return is_monomorphic; @@ -321,7 +322,7 @@ } -void CompiledIC::set_to_clean() { +void CompiledIC::set_to_clean(bool in_use) { assert(SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->is_locked() , "MT-unsafe call"); if (TraceInlineCacheClearing || TraceICs) { tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address())); @@ -337,7 +338,7 @@ // A zombie transition will always be safe, since the metadata has already been set to NULL, so // we only need to patch the destination - bool safe_transition = is_optimized() || SafepointSynchronize::is_at_safepoint(); + bool safe_transition = !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint(); if (safe_transition) { // Kill any leftover stub we might have too --- old/src/share/vm/code/compiledIC.hpp 2015-08-27 08:36:39.442134411 +0200 +++ new/src/share/vm/code/compiledIC.hpp 2015-08-27 08:36:39.370134409 +0200 @@ -214,7 +214,7 @@ // // They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full. // - void set_to_clean(); + void set_to_clean(bool in_use = true); void set_to_monomorphic(CompiledICInfo& info); void clear_ic_stub(); --- old/src/share/vm/code/nmethod.cpp 2015-08-27 08:36:39.766134420 +0200 +++ new/src/share/vm/code/nmethod.cpp 2015-08-27 08:36:39.686134418 +0200 @@ -1050,7 +1050,7 @@ if( cb != NULL && cb->is_nmethod() ) { nmethod* nm = (nmethod*)cb; // Clean inline caches pointing to zombie, non-entrant and unloaded methods - if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(); + if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(is_alive()); } break; } --- old/src/share/vm/runtime/sweeper.cpp 2015-08-27 08:36:40.098134429 +0200 +++ new/src/share/vm/runtime/sweeper.cpp 2015-08-27 08:36:40.022134427 +0200 @@ -645,6 +645,12 @@ assert(result == None, "sanity"); result = Flushed; } else { + { + // Clean ICs of unloaded nmethods as well because they may reference other + // unloaded nmethods that may be flushed earlier in the sweeper cycle. + MutexLocker cl(CompiledIC_lock); + nm->cleanup_inline_caches(); + } // Code cache state change is tracked in make_zombie() nm->make_zombie(); SWEEP(nm);