--- old/src/share/vm/code/codeCache.cpp 2015-08-21 17:13:37.209159967 +0200 +++ new/src/share/vm/code/codeCache.cpp 2015-08-21 17:13:37.137159970 +0200 @@ -746,14 +746,17 @@ void CodeCache::gc_epilogue() { assert_locked_or_safepoint(CodeCache_lock); NMethodIterator iter; - while(iter.next_alive()) { + while(iter.next()) { nmethod* nm = iter.method(); - assert(!nm->is_unloaded(), "Tautology"); - if (needs_cache_clean()) { - nm->cleanup_inline_caches(); + 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()); } - DEBUG_ONLY(nm->verify()); - DEBUG_ONLY(nm->verify_oop_relocations()); } set_needs_cache_clean(false); prune_scavenge_root_nmethods(); @@ -993,29 +996,6 @@ return number_of_marked_CodeBlobs; } -void CodeCache::make_marked_nmethods_zombies() { - assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); - NMethodIterator iter; - while(iter.next_alive()) { - nmethod* nm = iter.method(); - if (nm->is_marked_for_deoptimization()) { - - // If the nmethod has already been made non-entrant and it can be converted - // then zombie it now. Otherwise make it non-entrant and it will eventually - // be zombied when it is no longer seen on the stack. Note that the nmethod - // might be "entrant" and not on the stack and so could be zombied immediately - // but we can't tell because we don't track it on stack until it becomes - // non-entrant. - - if (nm->is_not_entrant() && nm->can_not_entrant_be_converted()) { - nm->make_zombie(); - } else { - nm->make_not_entrant(); - } - } - } -} - void CodeCache::make_marked_nmethods_not_entrant() { assert_locked_or_safepoint(CodeCache_lock); NMethodIterator iter; @@ -1072,7 +1052,7 @@ // Deoptimize all activations depending on marked nmethods Deoptimization::deoptimize_dependents(); - // Make the dependent methods not entrant (in VM_Deoptimize they are made zombies) + // Make the dependent methods not entrant make_marked_nmethods_not_entrant(); } } @@ -1102,7 +1082,7 @@ // Deoptimize all activations depending on marked nmethods Deoptimization::deoptimize_dependents(); - // Make the dependent methods not entrant (in VM_Deoptimize they are made zombies) + // Make the dependent methods not entrant make_marked_nmethods_not_entrant(); } } --- old/src/share/vm/code/codeCache.hpp 2015-08-21 17:13:37.493159954 +0200 +++ new/src/share/vm/code/codeCache.hpp 2015-08-21 17:13:37.425159957 +0200 @@ -225,7 +225,6 @@ public: static void mark_all_nmethods_for_deoptimization(); static int mark_for_deoptimization(Method* dependee); - static void make_marked_nmethods_zombies(); static void make_marked_nmethods_not_entrant(); // Flushing and deoptimization --- old/src/share/vm/code/compiledIC.cpp 2015-08-21 17:13:37.761159941 +0200 +++ new/src/share/vm/code/compiledIC.cpp 2015-08-21 17:13:37.689159944 +0200 @@ -343,8 +343,8 @@ // Kill any leftover stub we might have too clear_ic_stub(); if (is_optimized()) { - set_ic_destination(entry); - } else { + set_ic_destination(entry); + } else { set_ic_destination_and_value(entry, (void*)NULL); } } else { --- old/src/share/vm/code/compiledIC.hpp 2015-08-21 17:13:38.049159928 +0200 +++ new/src/share/vm/code/compiledIC.hpp 2015-08-21 17:13:37.973159931 +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(); // Can only be called during a safepoint operation + void set_to_clean(); void set_to_monomorphic(CompiledICInfo& info); void clear_ic_stub(); --- old/src/share/vm/code/nmethod.cpp 2015-08-21 17:13:38.329159915 +0200 +++ new/src/share/vm/code/nmethod.cpp 2015-08-21 17:13:38.253159918 +0200 @@ -1021,7 +1021,6 @@ void nmethod::cleanup_inline_caches() { - assert_locked_or_safepoint(CompiledIC_lock); // If the method is not entrant or zombie then a JMP is plastered over the @@ -1037,7 +1036,8 @@ // In fact, why are we bothering to look at oops in a non-entrant method?? } - // Find all calls in an nmethod, and clear the ones that points to zombie methods + // Find all calls in an nmethod and clear the ones that point to non-entrant, + // zombie and unloaded nmethods. ResourceMark rm; RelocIterator iter(this, low_boundary); while(iter.next()) { @@ -1049,7 +1049,7 @@ CodeBlob *cb = CodeCache::find_blob_unsafe(ic->ic_destination()); if( cb != NULL && cb->is_nmethod() ) { nmethod* nm = (nmethod*)cb; - // Clean inline caches pointing to both zombie and not_entrant methods + // Clean inline caches pointing to zombie, non-entrant and unloaded methods if (!nm->is_in_use() || (nm->method()->code() != nm)) ic->set_to_clean(); } break; @@ -1059,7 +1059,7 @@ CodeBlob *cb = CodeCache::find_blob_unsafe(csc->destination()); if( cb != NULL && cb->is_nmethod() ) { nmethod* nm = (nmethod*)cb; - // Clean inline caches pointing to both zombie and not_entrant methods + // Clean inline caches pointing to zombie, non-entrant and unloaded methods if (!nm->is_in_use() || (nm->method()->code() != nm)) csc->set_to_clean(); } break; @@ -2529,7 +2529,7 @@ // Hmm. OSR methods can be deopted but not marked as zombie or not_entrant // seems odd. - if( is_zombie() || is_not_entrant() ) + if (is_zombie() || is_not_entrant() || is_unloaded()) return; // Make sure all the entry points are correctly aligned for patching. --- old/src/share/vm/prims/jvmtiRedefineClasses.cpp 2015-08-21 17:13:38.645159900 +0200 +++ new/src/share/vm/prims/jvmtiRedefineClasses.cpp 2015-08-21 17:13:38.569159903 +0200 @@ -3771,7 +3771,7 @@ // Deoptimize all activations depending on marked nmethods Deoptimization::deoptimize_dependents(); - // Make the dependent methods not entrant (in VM_Deoptimize they are made zombies) + // Make the dependent methods not entrant CodeCache::make_marked_nmethods_not_entrant(); // From now on we know that the dependency information is complete --- old/src/share/vm/runtime/sweeper.cpp 2015-08-21 17:13:38.937159886 +0200 +++ new/src/share/vm/runtime/sweeper.cpp 2015-08-21 17:13:38.857159890 +0200 @@ -618,19 +618,14 @@ MutexLocker cl(CompiledIC_lock); nm->clear_ic_stubs(); } - // Acquiring the CompiledIC_lock may block for a safepoint and set the - // nmethod to zombie (see 'CodeCache::make_marked_nmethods_zombies'). - // Check if nmethod is still non-entrant at this point. - if (nm->is_not_entrant()) { - if (PrintMethodFlushing && Verbose) { - tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); - } - // Code cache state change is tracked in make_zombie() - nm->make_zombie(); - SWEEP(nm); - assert(result == None, "sanity"); - result = MadeZombie; + if (PrintMethodFlushing && Verbose) { + tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); } + // Code cache state change is tracked in make_zombie() + nm->make_zombie(); + SWEEP(nm); + assert(result == None, "sanity"); + result = MadeZombie; assert(nm->is_zombie(), "nmethod must be zombie"); } else { // Still alive, clean up its inline caches --- old/src/share/vm/runtime/vm_operations.cpp 2015-08-21 17:13:39.253159872 +0200 +++ new/src/share/vm/runtime/vm_operations.cpp 2015-08-21 17:13:39.173159875 +0200 @@ -110,7 +110,7 @@ Deoptimization::deoptimize_dependents(); // Make the dependent methods zombies - CodeCache::make_marked_nmethods_zombies(); + CodeCache::make_marked_nmethods_not_entrant(); } void VM_MarkActiveNMethods::doit() {