8209624: [JVMCI] Invalidate nmethods instead of directly unloading them when the InstalledCode is dropped
authornever
Tue, 21 Aug 2018 08:38:02 -0700
changeset 51473 871581ff5ce5
parent 51472 eb97d1a319f9
child 51474 0cb2d4391e16
8209624: [JVMCI] Invalidate nmethods instead of directly unloading them when the InstalledCode is dropped Reviewed-by: kvn
src/hotspot/share/aot/aotCompiledMethod.cpp
src/hotspot/share/aot/aotCompiledMethod.hpp
src/hotspot/share/code/compiledMethod.hpp
src/hotspot/share/code/nmethod.cpp
src/hotspot/share/code/nmethod.hpp
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp	Tue Aug 21 10:37:02 2018 -0400
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp	Tue Aug 21 08:38:02 2018 -0700
@@ -362,7 +362,7 @@
   log->print(" aot='%2d'", _heap->dso_id());
 }
 
-void AOTCompiledMethod::log_state_change() const {
+void AOTCompiledMethod::log_state_change(oop cause) const {
   if (LogCompilation) {
     ResourceMark m;
     if (xtty != NULL) {
--- a/src/hotspot/share/aot/aotCompiledMethod.hpp	Tue Aug 21 10:37:02 2018 -0400
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp	Tue Aug 21 08:38:02 2018 -0700
@@ -193,7 +193,7 @@
   virtual int comp_level() const { return CompLevel_aot; }
   virtual address verified_entry_point() const { return _code + _meta->verified_entry_offset(); }
   virtual void log_identity(xmlStream* stream) const;
-  virtual void log_state_change() const;
+  virtual void log_state_change(oop cause = NULL) const;
   virtual bool make_entrant() NOT_TIERED({ ShouldNotReachHere(); return false; });
   virtual bool make_not_entrant() { return make_not_entrant_helper(not_entrant); }
   virtual bool make_not_used() { return make_not_entrant_helper(not_used); }
--- a/src/hotspot/share/code/compiledMethod.hpp	Tue Aug 21 10:37:02 2018 -0400
+++ b/src/hotspot/share/code/compiledMethod.hpp	Tue Aug 21 08:38:02 2018 -0700
@@ -202,7 +202,7 @@
 
   virtual address verified_entry_point() const = 0;
   virtual void log_identity(xmlStream* log) const = 0;
-  virtual void log_state_change() const = 0;
+  virtual void log_state_change(oop cause = NULL) const = 0;
   virtual bool make_not_used() = 0;
   virtual bool make_not_entrant() = 0;
   virtual bool make_entrant() = 0;
--- a/src/hotspot/share/code/nmethod.cpp	Tue Aug 21 10:37:02 2018 -0400
+++ b/src/hotspot/share/code/nmethod.cpp	Tue Aug 21 08:38:02 2018 -0700
@@ -422,7 +422,7 @@
 #if INCLUDE_JVMCI
   _jvmci_installed_code   = NULL;
   _speculation_log        = NULL;
-  _jvmci_installed_code_triggers_unloading = false;
+  _jvmci_installed_code_triggers_invalidation = false;
 #endif
 }
 
@@ -690,9 +690,9 @@
     _speculation_log = speculation_log;
     oop obj = JNIHandles::resolve(installed_code);
     if (obj == NULL || (obj->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(obj))) {
-      _jvmci_installed_code_triggers_unloading = false;
+      _jvmci_installed_code_triggers_invalidation = false;
     } else {
-      _jvmci_installed_code_triggers_unloading = true;
+      _jvmci_installed_code_triggers_invalidation = true;
     }
 
     if (compiler->is_jvmci()) {
@@ -786,6 +786,13 @@
   if (TieredCompilation) {
     log->print(" level='%d'", comp_level());
   }
+#if INCLUDE_JVMCI
+    char buffer[O_BUFLEN];
+    char* jvmci_name = jvmci_installed_code_name(buffer, O_BUFLEN);
+    if (jvmci_name != NULL) {
+      log->print(" jvmci_installed_code_name='%s'", jvmci_name);
+    }
+#endif
 }
 
 
@@ -1083,7 +1090,7 @@
   _state = unloaded;
 
   // Log the unloading.
-  log_state_change();
+  log_state_change(cause);
 
 #if INCLUDE_JVMCI
   // The method can only be unloaded after the pointer to the installed code
@@ -1107,7 +1114,7 @@
   }
 }
 
-void nmethod::log_state_change() const {
+void nmethod::log_state_change(oop cause) const {
   if (LogCompilation) {
     if (xtty != NULL) {
       ttyLocker ttyl;  // keep the following output all in one block
@@ -1120,6 +1127,9 @@
                          (_state == zombie ? " zombie='1'" : ""));
       }
       log_identity(xtty);
+      if (cause != NULL) {
+        xtty->print(" cause='%s'", cause->klass()->external_name());
+      }
       xtty->stamp();
       xtty->end_elem();
     }
@@ -1150,7 +1160,8 @@
   // 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());
-  NoSafepointVerifier nsv;
+  // This can be called while the system is already at a safepoint which is ok
+  NoSafepointVerifier nsv(true, !SafepointSynchronize::is_at_safepoint());
 
   // during patching, depending on the nmethod state we must notify the GC that
   // code has been unloaded, unregistering it. We cannot do this right while
@@ -1507,13 +1518,12 @@
 bool nmethod::do_unloading_jvmci() {
   if (_jvmci_installed_code != NULL) {
     if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
-      if (_jvmci_installed_code_triggers_unloading) {
-        // jweak reference processing has already cleared the referent
-        make_unloaded(NULL);
-        return true;
-      } else {
-        clear_jvmci_installed_code();
+      if (_jvmci_installed_code_triggers_invalidation) {
+        // The reference to the installed code has been dropped so invalidate
+        // this nmethod and allow the sweeper to reclaim it.
+        make_not_entrant();
       }
+      clear_jvmci_installed_code();
     }
   }
   return false;
@@ -2948,7 +2958,7 @@
   return JNIHandles::resolve(_speculation_log);
 }
 
-char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
+char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) const {
   if (!this->is_compiled_by_jvmci()) {
     return NULL;
   }
--- a/src/hotspot/share/code/nmethod.hpp	Tue Aug 21 10:37:02 2018 -0400
+++ b/src/hotspot/share/code/nmethod.hpp	Tue Aug 21 08:38:02 2018 -0700
@@ -78,7 +78,7 @@
   // That is, installed code other than a "default"
   // HotSpotNMethod causes nmethod unloading.
   // This field is ignored once _jvmci_installed_code is NULL.
-  bool _jvmci_installed_code_triggers_unloading;
+  bool _jvmci_installed_code_triggers_invalidation;
 #endif
 
   // To support simple linked-list chaining of nmethods:
@@ -456,7 +456,7 @@
   // Copies the value of the name field in the InstalledCode
   // object (if any) associated with this nmethod into buf.
   // Returns the value of buf if it was updated otherwise NULL.
-  char* jvmci_installed_code_name(char* buf, size_t buflen);
+  char* jvmci_installed_code_name(char* buf, size_t buflen) const;
 
   // Updates the state of the InstalledCode (if any) associated with
   // this nmethod based on the current value of _state.
@@ -486,7 +486,7 @@
  protected:
   virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive);
 #if INCLUDE_JVMCI
-  // See comment for _jvmci_installed_code_triggers_unloading field.
+  // See comment for _jvmci_installed_code_triggers_invalidation field.
   // Returns whether this nmethod was unloaded.
   virtual bool do_unloading_jvmci();
 #endif
@@ -555,7 +555,7 @@
   // Logging
   void log_identity(xmlStream* log) const;
   void log_new_nmethod() const;
-  void log_state_change() const;
+  void log_state_change(oop cause = NULL) const;
 
   // Prints block-level comments, including nmethod specific block labels:
   virtual void print_block_comment(outputStream* stream, address block_begin) const {