< prev index next >
src/hotspot/share/code/nmethod.cpp
// Tell if a non-entrant method can be converted to a zombie (i.e.,
// there are no activations on the stack, not in use by the VM,
// and not in use by the ServiceThread)
bool nmethod::can_convert_to_zombie() {
! assert(is_not_entrant(), "must be a non-entrant method");
// Since the nmethod sweeper only does partial sweep the sweeper's traversal
// count can be greater than the stack traversal count before it hits the
// nmethod for the second time.
! return stack_traversal_mark()+1 < NMethodSweeper::traversal_count() &&
! !is_locked_by_vm();
}
void nmethod::inc_decompile_count() {
if (!is_compiled_by_c2() && !is_compiled_by_jvmci()) return;
// Could be gated by ProfileTraps, but do not bother...
// Tell if a non-entrant method can be converted to a zombie (i.e.,
// there are no activations on the stack, not in use by the VM,
// and not in use by the ServiceThread)
bool nmethod::can_convert_to_zombie() {
! assert(is_not_entrant() || is_unloading(), "must be a non-entrant method");
// Since the nmethod sweeper only does partial sweep the sweeper's traversal
// count can be greater than the stack traversal count before it hits the
// nmethod for the second time.
! return stack_traversal_mark() + 1 < NMethodSweeper::traversal_count() &&
! !is_locked_by_vm() && (!is_unloading() || is_unloaded());
}
void nmethod::inc_decompile_count() {
if (!is_compiled_by_c2() && !is_compiled_by_jvmci()) return;
// Could be gated by ProfileTraps, but do not bother...
***************
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
// Unregister must be done before the state change
Universe::heap()->unregister_nmethod(this);
- _state = unloaded;
-
// Log the unloading.
log_state_change();
#if INCLUDE_JVMCI
// The method can only be unloaded after the pointer to the installed code
***************
// The Method* is gone at this point
assert(_method == NULL, "Tautology");
set_osr_link(NULL);
NMethodSweeper::report_state_change(this);
+
+ // The release is only needed for compile-time ordering, as accesses
+ // into the nmethod after the store is not safe, due to the sweeper
+ // being allowed to free it then, in the case of concurrent nmethod
+ // unloading. Therefore, there is no need for acquire on the loader side.
+ OrderAccess::release_store(&_state, (signed char)unloaded);
}
void nmethod::invalidate_osr_method() {
assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
// Remove from list of active nmethods
***************
DepTable* table = new DepTable();
// Iterate over live nmethods and check dependencies of all nmethods that are not
// marked for deoptimization. A particular dependency is only checked once.
! NMethodIterator iter;
while(iter.next()) {
nmethod* nm = iter.method();
// Only notify for live nmethods
! if (nm->is_alive() && !nm->is_marked_for_deoptimization()) {
for (Dependencies::DepStream deps(nm); deps.next(); ) {
// Construct abstraction of a dependency.
DependencySignature* current_sig = new DependencySignature(deps);
// Determine if dependency is already checked. table->put(...) returns
DepTable* table = new DepTable();
// Iterate over live nmethods and check dependencies of all nmethods that are not
// marked for deoptimization. A particular dependency is only checked once.
! NMethodIterator iter(true /* only_alive */, true /* only_not_unloading */);
while(iter.next()) {
nmethod* nm = iter.method();
// Only notify for live nmethods
! if (!nm->is_marked_for_deoptimization()) {
for (Dependencies::DepStream deps(nm); deps.next(); ) {
// Construct abstraction of a dependency.
DependencySignature* current_sig = new DependencySignature(deps);
// Determine if dependency is already checked. table->put(...) returns
***************
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.
InstalledCode::set_address(installed_code, 0);
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() || is_unloading()) {
// 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.
InstalledCode::set_address(installed_code, 0);
***************
// 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();
}
// be invalidated.
InstalledCode::set_entryPoint(installed_code, 0);
}
}
}
! if (!is_alive() || is_unloading()) {
// 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();
}
***************
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
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->is_unloading() || nm->jvmci_installed_code() == installedCode(), "sanity check");
}
#endif
if (nm->is_alive()) {
// Invalidating the InstalledCode means we want the nmethod
< prev index next >