# HG changeset patch # User never # Date 1534865882 25200 # Node ID 871581ff5ce579d27e94b7a328396779f227cfad # Parent eb97d1a319f970e7cdb2ceb4572ade478cff70d8 8209624: [JVMCI] Invalidate nmethods instead of directly unloading them when the InstalledCode is dropped Reviewed-by: kvn diff -r eb97d1a319f9 -r 871581ff5ce5 src/hotspot/share/aot/aotCompiledMethod.cpp --- 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) { diff -r eb97d1a319f9 -r 871581ff5ce5 src/hotspot/share/aot/aotCompiledMethod.hpp --- 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); } diff -r eb97d1a319f9 -r 871581ff5ce5 src/hotspot/share/code/compiledMethod.hpp --- 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; diff -r eb97d1a319f9 -r 871581ff5ce5 src/hotspot/share/code/nmethod.cpp --- 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; } diff -r eb97d1a319f9 -r 871581ff5ce5 src/hotspot/share/code/nmethod.hpp --- 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 {