--- old/src/share/vm/code/nmethod.cpp 2013-09-10 08:51:57.914915976 +0200 +++ new/src/share/vm/code/nmethod.cpp 2013-09-10 08:51:57.794915979 +0200 @@ -1296,10 +1296,17 @@ } // Common functionality for both make_not_entrant and make_zombie -bool nmethod::make_not_entrant_or_zombie(unsigned int state) { - assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); +bool nmethod::make_not_entrant_or_zombie(unsigned int new_state) { + assert(new_state == zombie || new_state == not_entrant, "must become zombie or not_entrant"); assert(!is_zombie(), "should not already be a zombie"); + // The state of nmethods that are currently locked by the VM must not change. + // Some operations such as setting ICs (e.g., SharedRuntime::resolve_sub_helper()) + // rely on this fact. + if (is_locked_by_vm()) { + return false; + } + // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. nmethodLocker nml(this); methodHandle the_method(method()); @@ -1325,10 +1332,10 @@ // Enter critical section. Does not block for safepoint. MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag); - if (_state == state) { + if (_state == new_state) { // another thread already performed this transition so nothing - // to do, but return false to indicate this. - return false; + // to do, but return true to indicate this. + return true; } // The caller can be calling the method statically or through an inline @@ -1347,12 +1354,12 @@ // If the state is becoming a zombie, signal to unregister the nmethod with // the heap. // This nmethod may have already been unloaded during a full GC. - if ((state == zombie) && !is_unloaded()) { + if ((new_state == zombie) && !is_unloaded()) { nmethod_needs_unregister = true; } // Change state - _state = state; + _state = new_state; // Log the transition once log_state_change(); @@ -1370,7 +1377,7 @@ method()->clear_code(); } - if (state == not_entrant) { + if (new_state == not_entrant) { mark_as_seen_on_stack(); } @@ -1380,7 +1387,7 @@ // dependencies must be flushed. nmethods in the not_entrant // state will be flushed later when the transition to zombie // happens or they get unloaded. - if (state == zombie) { + if (new_state == zombie) { { // Flushing dependecies must be done before any possible // safepoint can sneak in, otherwise the oops used by the @@ -1408,16 +1415,15 @@ // nmethod is in zombie state set_method(NULL); } else { - assert(state == not_entrant, "other cases may need to be handled differently"); + assert(new_state == not_entrant, "other cases may need to be handled differently"); } if (TraceCreateZombies) { - tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (state == not_entrant) ? "not entrant" : "zombie"); + tty->print_cr("nmethod <" INTPTR_FORMAT "> code made %s", this, (new_state == not_entrant) ? "not entrant" : "zombie"); } // Make sweeper aware that there is a zombie method that needs to be removed NMethodSweeper::notify(this); - return true; }