< prev index next >
src/hotspot/share/code/nmethod.cpp
Print this page
*** 407,416 ****
--- 407,417 ----
_rtm_state = NoRTM;
#endif
#if INCLUDE_JVMCI
_jvmci_installed_code = NULL;
_speculation_log = NULL;
+ _jvmci_installed_code_triggers_unloading = false;
#endif
}
nmethod* nmethod::new_native_nmethod(const methodHandle& method,
int compile_id,
*** 459,470 ****
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
! , Handle installed_code,
! Handle speculationLog
#endif
)
{
assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
code_buffer->finalize_oop_references(method);
--- 460,471 ----
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
! , jweak installed_code,
! jweak speculationLog
#endif
)
{
assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
code_buffer->finalize_oop_references(method);
*** 640,651 ****
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
! , Handle installed_code,
! Handle speculation_log
#endif
)
: CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false),
_native_receiver_sp_offset(in_ByteSize(-1)),
_native_basic_lock_sp_offset(in_ByteSize(-1))
--- 641,652 ----
ExceptionHandlerTable* handler_table,
ImplicitExceptionTable* nul_chk_table,
AbstractCompiler* compiler,
int comp_level
#if INCLUDE_JVMCI
! , jweak installed_code,
! jweak speculation_log
#endif
)
: CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false),
_native_receiver_sp_offset(in_ByteSize(-1)),
_native_basic_lock_sp_offset(in_ByteSize(-1))
*** 669,680 ****
_consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts());
_stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs());
set_ctable_begin(header_begin() + _consts_offset);
#if INCLUDE_JVMCI
! _jvmci_installed_code = installed_code();
! _speculation_log = (instanceOop)speculation_log();
if (compiler->is_jvmci()) {
// JVMCI might not produce any stub sections
if (offsets->value(CodeOffsets::Exceptions) != -1) {
_exception_offset = code_offset() + offsets->value(CodeOffsets::Exceptions);
--- 670,687 ----
_consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts());
_stub_offset = content_offset() + code_buffer->total_offset_of(code_buffer->stubs());
set_ctable_begin(header_begin() + _consts_offset);
#if INCLUDE_JVMCI
! _jvmci_installed_code = installed_code;
! _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;
! } else {
! _jvmci_installed_code_triggers_unloading = true;
! }
if (compiler->is_jvmci()) {
// JVMCI might not produce any stub sections
if (offsets->value(CodeOffsets::Exceptions) != -1) {
_exception_offset = code_offset() + offsets->value(CodeOffsets::Exceptions);
*** 1024,1035 ****
LogStream ls(lt);
ls.print_cr("making nmethod " INTPTR_FORMAT
" unloadable, Method*(" INTPTR_FORMAT
"), cause(" INTPTR_FORMAT ")",
p2i(this), p2i(_method), p2i(cause));
- if (!Universe::heap()->is_gc_active())
- cause->klass()->print_on(&ls);
}
// Unlink the osr method, so we do not look this up again
if (is_osr_method()) {
// Invalidate the osr nmethod only once
if (is_in_use()) {
--- 1031,1040 ----
*** 1075,1092 ****
log_state_change();
#if INCLUDE_JVMCI
// The method can only be unloaded after the pointer to the installed code
// Java wrapper is no longer alive. Here we need to clear out this weak
! // reference to the dead object. Nulling out the reference has to happen
! // after the method is unregistered since the original value may be still
! // tracked by the rset.
maybe_invalidate_installed_code();
- // Clear these out after the nmethod has been unregistered and any
- // updates to the InstalledCode instance have been performed.
- _jvmci_installed_code = NULL;
- _speculation_log = NULL;
#endif
// The Method* is gone at this point
assert(_method == NULL, "Tautology");
--- 1080,1091 ----
log_state_change();
#if INCLUDE_JVMCI
// The method can only be unloaded after the pointer to the installed code
// Java wrapper is no longer alive. Here we need to clear out this weak
! // reference to the dead object.
maybe_invalidate_installed_code();
#endif
// The Method* is gone at this point
assert(_method == NULL, "Tautology");
*** 1244,1257 ****
// 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);
if (nmethod_needs_unregister) {
Universe::heap()->unregister_nmethod(this);
- #ifdef JVMCI
- _jvmci_installed_code = NULL;
- _speculation_log = NULL;
- #endif
}
flush_dependencies(NULL);
}
// zombie only - if a JVMTI agent has enabled the CompiledMethodUnload
--- 1243,1252 ----
*** 1312,1321 ****
--- 1307,1321 ----
if (on_scavenge_root_list()) {
CodeCache::drop_scavenge_root_nmethod(this);
}
+ #if INCLUDE_JVMCI
+ assert(_jvmci_installed_code == NULL, "should have been nulled out when transitioned to zombie");
+ assert(_speculation_log == NULL, "should have been nulled out when transitioned to zombie");
+ #endif
+
CodeBlob::flush();
CodeCache::free(this);
}
//
*** 1498,1530 ****
return do_unloading_scopes(is_alive, unloading_occurred);
}
#if INCLUDE_JVMCI
bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) {
- bool is_unloaded = false;
- // Follow JVMCI method
- BarrierSet* bs = Universe::heap()->barrier_set();
if (_jvmci_installed_code != NULL) {
! if (_jvmci_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_jvmci_installed_code)) {
! if (!is_alive->do_object_b(_jvmci_installed_code)) {
! clear_jvmci_installed_code();
! }
! } else {
! if (can_unload(is_alive, (oop*)&_jvmci_installed_code, unloading_occurred)) {
return true;
}
}
}
!
! if (_speculation_log != NULL) {
! if (!is_alive->do_object_b(_speculation_log)) {
! bs->write_ref_nmethod_pre(&_speculation_log, this);
! _speculation_log = NULL;
! bs->write_ref_nmethod_post(&_speculation_log, this);
! }
! }
! return is_unloaded;
}
#endif
// Iterate over metadata calling this function. Used by RedefineClasses
void nmethod::metadata_do(void f(Metadata*)) {
--- 1498,1519 ----
return do_unloading_scopes(is_alive, unloading_occurred);
}
#if INCLUDE_JVMCI
bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) {
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(is_alive, NULL);
return true;
+ } else {
+ clear_jvmci_installed_code();
}
}
}
! return false;
}
#endif
// Iterate over metadata calling this function. Used by RedefineClasses
void nmethod::metadata_do(void f(Metadata*)) {
*** 1592,1610 ****
low_boundary += NativeJump::instruction_size;
// %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump.
// (See comment above.)
}
- #if INCLUDE_JVMCI
- if (_jvmci_installed_code != NULL) {
- f->do_oop((oop*) &_jvmci_installed_code);
- }
- if (_speculation_log != NULL) {
- f->do_oop((oop*) &_speculation_log);
- }
- #endif
-
RelocIterator iter(this, low_boundary);
while (iter.next()) {
if (iter.type() == relocInfo::oop_type ) {
oop_Relocation* r = iter.oop_reloc();
--- 1581,1590 ----
*** 2858,2891 ****
#endif // !PRODUCT
#if INCLUDE_JVMCI
void nmethod::clear_jvmci_installed_code() {
! // write_ref_method_pre/post can only be safely called at a
! // safepoint or while holding the CodeCache_lock
! assert(CodeCache_lock->is_locked() ||
! SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
if (_jvmci_installed_code != NULL) {
! // This must be done carefully to maintain nmethod remembered sets properly
! BarrierSet* bs = Universe::heap()->barrier_set();
! bs->write_ref_nmethod_pre(&_jvmci_installed_code, this);
_jvmci_installed_code = NULL;
! bs->write_ref_nmethod_post(&_jvmci_installed_code, this);
}
}
void nmethod::maybe_invalidate_installed_code() {
assert(Patching_lock->is_locked() ||
SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
! oop installed_code = jvmci_installed_code();
if (installed_code != NULL) {
nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
! if (nm == NULL || nm != this) {
! // The link has been broken or the InstalledCode instance is
! // associated with another nmethod so do nothing.
! return;
! }
if (!is_alive()) {
// Break the link between nmethod and InstalledCode such that the nmethod
// can subsequently be flushed safely. The link must be maintained while
// the method could have live activations since invalidateInstalledCode
// might want to invalidate all existing activations.
--- 2838,2870 ----
#endif // !PRODUCT
#if INCLUDE_JVMCI
void nmethod::clear_jvmci_installed_code() {
! assert_locked_or_safepoint(Patching_lock);
if (_jvmci_installed_code != NULL) {
! JNIHandles::destroy_weak_global(_jvmci_installed_code);
_jvmci_installed_code = NULL;
! }
! }
!
! void nmethod::clear_speculation_log() {
! assert_locked_or_safepoint(Patching_lock);
! if (_speculation_log != NULL) {
! JNIHandles::destroy_weak_global(_speculation_log);
! _speculation_log = NULL;
}
}
void nmethod::maybe_invalidate_installed_code() {
assert(Patching_lock->is_locked() ||
SafepointSynchronize::is_at_safepoint(), "should be performed under a lock for consistency");
! oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
if (installed_code != NULL) {
+ // Update the values in the InstalledCode instance if it still refers to this nmethod
nmethod* nm = (nmethod*)InstalledCode::address(installed_code);
! if (nm == this) {
if (!is_alive()) {
// Break the link between nmethod and InstalledCode such that the nmethod
// can subsequently be flushed safely. The link must be maintained while
// the method could have live activations since invalidateInstalledCode
// might want to invalidate all existing activations.
*** 2896,2905 ****
--- 2875,2891 ----
// the address link around that so that existing activations can
// be invalidated.
InstalledCode::set_entryPoint(installed_code, 0);
}
}
+ }
+ if (!is_alive()) {
+ // Clear these out after the nmethod has been unregistered and any
+ // updates to the InstalledCode instance have been performed.
+ clear_jvmci_installed_code();
+ clear_speculation_log();
+ }
}
void nmethod::invalidate_installed_code(Handle installedCode, TRAPS) {
if (installedCode() == NULL) {
THROW(vmSymbols::java_lang_NullPointerException());
*** 2914,2960 ****
nmethodLocker nml(nm);
#ifdef ASSERT
{
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
// This relationship can only be checked safely under a lock
! assert(nm == NULL || !nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check");
}
#endif
if (nm->is_alive()) {
! // The nmethod state machinery maintains the link between the
! // HotSpotInstalledCode and nmethod* so as long as the nmethod appears to be
! // alive assume there is work to do and deoptimize the nmethod.
nm->mark_for_deoptimization();
VM_Deoptimize op;
VMThread::execute(&op);
}
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
- // Check that it's still associated with the same nmethod and break
- // the link if it is.
if (InstalledCode::address(installedCode) == nativeMethod) {
InstalledCode::set_address(installedCode, 0);
}
}
char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
if (!this->is_compiled_by_jvmci()) {
return NULL;
}
! oop installedCode = this->jvmci_installed_code();
! if (installedCode != NULL) {
! oop installedCodeName = NULL;
! if (installedCode->is_a(InstalledCode::klass())) {
! installedCodeName = InstalledCode::name(installedCode);
}
! if (installedCodeName != NULL) {
! return java_lang_String::as_utf8_string(installedCodeName, buf, (int)buflen);
! } else {
! jio_snprintf(buf, buflen, "null");
! return buf;
}
}
! jio_snprintf(buf, buflen, "noInstalledCode");
! return buf;
}
#endif
--- 2900,2950 ----
nmethodLocker nml(nm);
#ifdef ASSERT
{
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
// This relationship can only be checked safely under a lock
! assert(!nm->is_alive() || nm->jvmci_installed_code() == installedCode(), "sanity check");
}
#endif
if (nm->is_alive()) {
! // Invalidating the InstalledCode means we want the nmethod
! // to be deoptimized.
nm->mark_for_deoptimization();
VM_Deoptimize op;
VMThread::execute(&op);
}
+ // Multiple threads could reach this point so we now need to
+ // lock and re-check the link to the nmethod so that only one
+ // thread clears it.
MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
if (InstalledCode::address(installedCode) == nativeMethod) {
InstalledCode::set_address(installedCode, 0);
}
}
+ oop nmethod::jvmci_installed_code() {
+ return JNIHandles::resolve(_jvmci_installed_code);
+ }
+
+ oop nmethod::speculation_log() {
+ return JNIHandles::resolve(_speculation_log);
+ }
+
char* nmethod::jvmci_installed_code_name(char* buf, size_t buflen) {
if (!this->is_compiled_by_jvmci()) {
return NULL;
}
! oop installed_code = JNIHandles::resolve(_jvmci_installed_code);
! if (installed_code != NULL) {
! oop installed_code_name = NULL;
! if (installed_code->is_a(InstalledCode::klass())) {
! installed_code_name = InstalledCode::name(installed_code);
}
! if (installed_code_name != NULL) {
! return java_lang_String::as_utf8_string(installed_code_name, buf, (int)buflen);
}
}
! return NULL;
}
#endif
< prev index next >