src/share/vm/code/nmethod.cpp
Print this page
@@ -1294,14 +1294,21 @@
print_on(tty, _state == zombie ? "made zombie" : "made not entrant");
}
}
// 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());
No_Safepoint_Verifier nsv;
@@ -1323,14 +1330,14 @@
}
// 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
// cache call.
if (!is_osr_method() && !is_not_entrant()) {
@@ -1345,16 +1352,16 @@
}
// 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();
// Remove nmethod from method.
@@ -1368,21 +1375,21 @@
method()->from_compiled_entry() == verified_entry_point())) {
HandleMark hm;
method()->clear_code();
}
- if (state == not_entrant) {
+ if (new_state == not_entrant) {
mark_as_seen_on_stack();
}
} // leave critical region under Patching_lock
// When the nmethod becomes zombie it is no longer alive so the
// 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
// dependency logic could have become stale.
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
@@ -1406,20 +1413,19 @@
#endif
// the Method may be reclaimed by class unloading now that the
// 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;
}
void nmethod::flush() {
// Note that there are no valid oops in the nmethod anymore.