Skip to content
Permalink
Browse files
8266497: Remove unnecessary EMCP liveness indication
Reviewed-by: iklam, dholmes, sspitsyn
  • Loading branch information
coleenp committed May 5, 2021
1 parent 6ba911d commit a05e8e24224b047584c3a273fa7b4fef66798dd6
Showing with 14 additions and 69 deletions.
  1. +0 −47 src/hotspot/share/oops/instanceKlass.cpp
  2. +0 −2 src/hotspot/share/oops/method.cpp
  3. +3 −18 src/hotspot/share/oops/method.hpp
  4. +11 −2 src/hotspot/share/prims/jvmtiImpl.cpp
@@ -3989,30 +3989,6 @@ void InstanceKlass::purge_previous_version_list() {
_has_previous_versions = true;
}

// At least one method is live in this previous version.
// Reset dead EMCP methods not to get breakpoints.
// All methods are deallocated when all of the methods for this class are no
// longer running.
Array<Method*>* method_refs = pv_node->methods();
if (method_refs != NULL) {
log_trace(redefine, class, iklass, purge)("previous methods length=%d", method_refs->length());
for (int j = 0; j < method_refs->length(); j++) {
Method* method = method_refs->at(j);

if (!method->on_stack()) {
// no breakpoints for non-running methods
if (method->is_running_emcp()) {
method->set_running_emcp(false);
}
} else {
assert (method->is_obsolete() || method->is_running_emcp(),
"emcp method cannot run after emcp bit is cleared");
log_trace(redefine, class, iklass, purge)
("purge: %s(%s): prev method @%d in version @%d is alive",
method->name()->as_C_string(), method->signature()->as_C_string(), j, version);
}
}
}
// next previous version
last = pv_node;
pv_node = pv_node->previous_versions();
@@ -4112,29 +4088,6 @@ void InstanceKlass::add_previous_version(InstanceKlass* scratch_class,
return;
}

if (emcp_method_count != 0) {
// At least one method is still running, check for EMCP methods
for (int i = 0; i < old_methods->length(); i++) {
Method* old_method = old_methods->at(i);
if (!old_method->is_obsolete() && old_method->on_stack()) {
// if EMCP method (not obsolete) is on the stack, mark as EMCP so that
// we can add breakpoints for it.

// We set the method->on_stack bit during safepoints for class redefinition
// and use this bit to set the is_running_emcp bit.
// After the safepoint, the on_stack bit is cleared and the running emcp
// method may exit. If so, we would set a breakpoint in a method that
// is never reached, but this won't be noticeable to the programmer.
old_method->set_running_emcp(true);
log_trace(redefine, class, iklass, add)
("EMCP method %s is on_stack " INTPTR_FORMAT, old_method->name_and_sig_as_C_string(), p2i(old_method));
} else if (!old_method->is_obsolete()) {
log_trace(redefine, class, iklass, add)
("EMCP method %s is NOT on_stack " INTPTR_FORMAT, old_method->name_and_sig_as_C_string(), p2i(old_method));
}
}
}

// Add previous version if any methods are still running.
// Set has_previous_version flag for processing during class unloading.
_has_previous_versions = true;
@@ -2230,8 +2230,6 @@ void Method::set_on_stack(const bool value) {
if (value && !already_set) {
MetadataOnStackMark::record(this);
}
assert(!value || !is_old() || is_obsolete() || is_running_emcp(),
"emcp methods cannot run after emcp bit is cleared");
}

// Called when the class loader is unloaded to make all methods weak.
@@ -88,10 +88,9 @@ class Method : public Metadata {
_dont_inline = 1 << 2,
_hidden = 1 << 3,
_has_injected_profile = 1 << 4,
_running_emcp = 1 << 5,
_intrinsic_candidate = 1 << 6,
_reserved_stack_access = 1 << 7,
_scoped = 1 << 8
_intrinsic_candidate = 1 << 5,
_reserved_stack_access = 1 << 6,
_scoped = 1 << 7
};
mutable u2 _flags;

@@ -743,20 +742,6 @@ class Method : public Metadata {
bool is_deleted() const { return access_flags().is_deleted(); }
void set_is_deleted() { _access_flags.set_is_deleted(); }

bool is_running_emcp() const {
// EMCP methods are old but not obsolete or deleted. Equivalent
// Modulo Constant Pool means the method is equivalent except
// the constant pool and instructions that access the constant
// pool might be different.
// If a breakpoint is set in a redefined method, its EMCP methods that are
// still running must have a breakpoint also.
return (_flags & _running_emcp) != 0;
}

void set_running_emcp(bool x) {
_flags = x ? (_flags | _running_emcp) : (_flags & ~_running_emcp);
}

bool on_stack() const { return access_flags().on_stack(); }
void set_on_stack(const bool value);

@@ -243,8 +243,17 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {

for (int i = methods->length() - 1; i >= 0; i--) {
Method* method = methods->at(i);
// Only set breakpoints in running EMCP methods.
if (method->is_running_emcp() &&
// Only set breakpoints in EMCP methods.
// EMCP methods are old but not obsolete. Equivalent
// Modulo Constant Pool means the method is equivalent except
// the constant pool and instructions that access the constant
// pool might be different.
// If a breakpoint is set in a redefined method, its EMCP methods
// must have a breakpoint also.
// None of the methods are deleted until none are running.
// This code could set a breakpoint in a method that
// is never reached, but this won't be noticeable to the programmer.
if (!method->is_obsolete() &&
method->name() == m_name &&
method->signature() == m_signature) {
ResourceMark rm;

0 comments on commit a05e8e2

Please sign in to comment.