mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8209189: Make CompiledMethod::do_unloading more concurrent
Reviewed-by: kvn, coleenp
This commit is contained in:
parent
97d3dc7902
commit
25f14cd757
15 changed files with 309 additions and 447 deletions
|
@ -413,7 +413,6 @@ void nmethod::init_defaults() {
|
|||
_oops_do_mark_link = NULL;
|
||||
_jmethod_id = NULL;
|
||||
_osr_link = NULL;
|
||||
_unloading_next = NULL;
|
||||
_scavenge_root_link = NULL;
|
||||
_scavenge_root_state = 0;
|
||||
#if INCLUDE_RTM_OPT
|
||||
|
@ -599,6 +598,7 @@ nmethod::nmethod(
|
|||
|
||||
code_buffer->copy_code_and_locs_to(this);
|
||||
code_buffer->copy_values_to(this);
|
||||
|
||||
if (ScavengeRootsInCode) {
|
||||
Universe::heap()->register_nmethod(this);
|
||||
}
|
||||
|
@ -757,6 +757,7 @@ nmethod::nmethod(
|
|||
code_buffer->copy_values_to(this);
|
||||
debug_info->copy_to(this);
|
||||
dependencies->copy_to(this);
|
||||
clear_unloading_state();
|
||||
if (ScavengeRootsInCode) {
|
||||
Universe::heap()->register_nmethod(this);
|
||||
}
|
||||
|
@ -1025,8 +1026,7 @@ void nmethod::inc_decompile_count() {
|
|||
mdo->inc_decompile_count();
|
||||
}
|
||||
|
||||
void nmethod::make_unloaded(oop cause) {
|
||||
|
||||
void nmethod::make_unloaded() {
|
||||
post_compiled_method_unload();
|
||||
|
||||
// This nmethod is being unloaded, make sure that dependencies
|
||||
|
@ -1042,11 +1042,8 @@ void nmethod::make_unloaded(oop cause) {
|
|||
LogStream ls(lt);
|
||||
ls.print("making nmethod " INTPTR_FORMAT
|
||||
" unloadable, Method*(" INTPTR_FORMAT
|
||||
"), cause(" INTPTR_FORMAT ") ",
|
||||
p2i(this), p2i(_method), p2i(cause));
|
||||
if (cause != NULL) {
|
||||
cause->print_value_on(&ls);
|
||||
}
|
||||
") ",
|
||||
p2i(this), p2i(_method));
|
||||
ls.cr();
|
||||
}
|
||||
// Unlink the osr method, so we do not look this up again
|
||||
|
@ -1079,12 +1076,6 @@ void nmethod::make_unloaded(oop cause) {
|
|||
|
||||
// Make the class unloaded - i.e., change state and notify sweeper
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||
if (is_in_use()) {
|
||||
// Transitioning directly from live to unloaded -- so
|
||||
// we need to force a cache clean-up; remember this
|
||||
// for later on.
|
||||
CodeCache::set_needs_cache_clean(true);
|
||||
}
|
||||
|
||||
// Unregister must be done before the state change
|
||||
Universe::heap()->unregister_nmethod(this);
|
||||
|
@ -1092,7 +1083,7 @@ void nmethod::make_unloaded(oop cause) {
|
|||
_state = unloaded;
|
||||
|
||||
// Log the unloading.
|
||||
log_state_change(cause);
|
||||
log_state_change();
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
// The method can only be unloaded after the pointer to the installed code
|
||||
|
@ -1116,7 +1107,7 @@ void nmethod::invalidate_osr_method() {
|
|||
}
|
||||
}
|
||||
|
||||
void nmethod::log_state_change(oop cause) const {
|
||||
void nmethod::log_state_change() const {
|
||||
if (LogCompilation) {
|
||||
if (xtty != NULL) {
|
||||
ttyLocker ttyl; // keep the following output all in one block
|
||||
|
@ -1129,9 +1120,6 @@ void nmethod::log_state_change(oop cause) const {
|
|||
(_state == zombie ? " zombie='1'" : ""));
|
||||
}
|
||||
log_identity(xtty);
|
||||
if (cause != NULL) {
|
||||
xtty->print(" cause='%s'", cause->klass()->external_name());
|
||||
}
|
||||
xtty->stamp();
|
||||
xtty->end_elem();
|
||||
}
|
||||
|
@ -1380,21 +1368,6 @@ void nmethod::flush_dependencies(bool delete_immediately) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// If this oop is not live, the nmethod can be unloaded.
|
||||
bool nmethod::can_unload(BoolObjectClosure* is_alive, oop* root) {
|
||||
assert(root != NULL, "just checking");
|
||||
oop obj = *root;
|
||||
if (obj == NULL || is_alive->do_object_b(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// An nmethod might be unloaded simply because one of its constant oops has gone dead.
|
||||
// No actual classes need to be unloaded in order for this to occur.
|
||||
make_unloaded(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// post_compiled_method_load_event
|
||||
// new method for install_code() path
|
||||
|
@ -1468,70 +1441,6 @@ void nmethod::post_compiled_method_unload() {
|
|||
set_unload_reported();
|
||||
}
|
||||
|
||||
bool nmethod::unload_if_dead_at(RelocIterator* iter_at_oop, BoolObjectClosure *is_alive) {
|
||||
assert(iter_at_oop->type() == relocInfo::oop_type, "Wrong relocation type");
|
||||
|
||||
oop_Relocation* r = iter_at_oop->oop_reloc();
|
||||
// Traverse those oops directly embedded in the code.
|
||||
// Other oops (oop_index>0) are seen as part of scopes_oops.
|
||||
assert(1 == (r->oop_is_immediate()) +
|
||||
(r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()),
|
||||
"oop must be found in exactly one place");
|
||||
if (r->oop_is_immediate() && r->oop_value() != NULL) {
|
||||
// Unload this nmethod if the oop is dead.
|
||||
if (can_unload(is_alive, r->oop_addr())) {
|
||||
return true;;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool nmethod::do_unloading_scopes(BoolObjectClosure* is_alive) {
|
||||
// Scopes
|
||||
for (oop* p = oops_begin(); p < oops_end(); p++) {
|
||||
if (*p == Universe::non_oop_word()) continue; // skip non-oops
|
||||
if (can_unload(is_alive, p)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool nmethod::do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive) {
|
||||
// Compiled code
|
||||
|
||||
// Prevent extra code cache walk for platforms that don't have immediate oops.
|
||||
if (relocInfo::mustIterateImmediateOopsInCode()) {
|
||||
RelocIterator iter(this, low_boundary);
|
||||
while (iter.next()) {
|
||||
if (iter.type() == relocInfo::oop_type) {
|
||||
if (unload_if_dead_at(&iter, is_alive)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return do_unloading_scopes(is_alive);
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
bool nmethod::do_unloading_jvmci() {
|
||||
if (_jvmci_installed_code != NULL) {
|
||||
if (JNIHandles::is_global_weak_cleared(_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;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Iterate over metadata calling this function. Used by RedefineClasses
|
||||
void nmethod::metadata_do(void f(Metadata*)) {
|
||||
{
|
||||
|
@ -1579,6 +1488,34 @@ void nmethod::metadata_do(void f(Metadata*)) {
|
|||
if (_method != NULL) f(_method);
|
||||
}
|
||||
|
||||
|
||||
// This is called at the end of the strong tracing/marking phase of a
|
||||
// GC to unload an nmethod if it contains otherwise unreachable
|
||||
// oops.
|
||||
|
||||
void nmethod::do_unloading(bool unloading_occurred) {
|
||||
// Make sure the oop's ready to receive visitors
|
||||
assert(!is_zombie() && !is_unloaded(),
|
||||
"should not call follow on zombie or unloaded nmethod");
|
||||
|
||||
if (is_unloading()) {
|
||||
make_unloaded();
|
||||
} else {
|
||||
#if INCLUDE_JVMCI
|
||||
if (_jvmci_installed_code != NULL) {
|
||||
if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
|
||||
if (_jvmci_installed_code_triggers_invalidation) {
|
||||
make_not_entrant();
|
||||
}
|
||||
clear_jvmci_installed_code();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
unload_nmethod_caches(unloading_occurred);
|
||||
}
|
||||
}
|
||||
|
||||
void nmethod::oops_do(OopClosure* f, bool allow_zombie) {
|
||||
// make sure the oops ready to receive visitors
|
||||
assert(allow_zombie || !is_zombie(), "should not call follow on zombie nmethod");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue