8022887: Assertion hit while using class and redefining it with RedefineClasses simultaneously

Need to refetch each method from InstanceKlass after all safepoints.  Removed leaky PreviousVersionInfo code.

Reviewed-by: dcubed, sspitsyn
This commit is contained in:
Coleen Phillimore 2013-09-20 09:30:02 -04:00
parent d2b68f0d0f
commit ec5e07f810
8 changed files with 169 additions and 304 deletions

View file

@ -273,59 +273,49 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
// add/remove breakpoint to/from versions of the method that
// are EMCP. Directly or transitively obsolete methods are
// not saved in the PreviousVersionInfo.
// not saved in the PreviousVersionNodes.
Thread *thread = Thread::current();
instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
Symbol* m_name = _method->name();
Symbol* m_signature = _method->signature();
{
ResourceMark rm(thread);
// PreviousVersionInfo objects returned via PreviousVersionWalker
// contain a GrowableArray of handles. We have to clean up the
// GrowableArray _after_ the PreviousVersionWalker destructor
// has destroyed the handles.
{
// search previous versions if they exist
PreviousVersionWalker pvw((InstanceKlass *)ikh());
for (PreviousVersionInfo * pv_info = pvw.next_previous_version();
pv_info != NULL; pv_info = pvw.next_previous_version()) {
GrowableArray<methodHandle>* methods =
pv_info->prev_EMCP_method_handles();
// search previous versions if they exist
PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh());
for (PreviousVersionNode * pv_node = pvw.next_previous_version();
pv_node != NULL; pv_node = pvw.next_previous_version()) {
GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods();
if (methods == NULL) {
// We have run into a PreviousVersion generation where
// all methods were made obsolete during that generation's
// RedefineClasses() operation. At the time of that
// operation, all EMCP methods were flushed so we don't
// have to go back any further.
//
// A NULL methods array is different than an empty methods
// array. We cannot infer any optimizations about older
// generations from an empty methods array for the current
// generation.
break;
}
if (methods == NULL) {
// We have run into a PreviousVersion generation where
// all methods were made obsolete during that generation's
// RedefineClasses() operation. At the time of that
// operation, all EMCP methods were flushed so we don't
// have to go back any further.
//
// A NULL methods array is different than an empty methods
// array. We cannot infer any optimizations about older
// generations from an empty methods array for the current
// generation.
break;
}
for (int i = methods->length() - 1; i >= 0; i--) {
methodHandle method = methods->at(i);
// obsolete methods that are running are not deleted from
// previous version array, but they are skipped here.
if (!method->is_obsolete() &&
method->name() == m_name &&
method->signature() == m_signature) {
RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
meth_act == &Method::set_breakpoint ? "sett" : "clear",
method->name()->as_C_string(),
method->signature()->as_C_string()));
for (int i = methods->length() - 1; i >= 0; i--) {
Method* method = methods->at(i);
// obsolete methods that are running are not deleted from
// previous version array, but they are skipped here.
if (!method->is_obsolete() &&
method->name() == m_name &&
method->signature() == m_signature) {
RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
meth_act == &Method::set_breakpoint ? "sett" : "clear",
method->name()->as_C_string(),
method->signature()->as_C_string()));
((Method*)method()->*meth_act)(_bci);
break;
}
}
(method->*meth_act)(_bci);
break;
}
} // pvw is cleaned up
} // rm is cleaned up
}
}
}
void JvmtiBreakpoint::set() {