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.