RFR 8055008: Clean up code that saves the previous versions of redefined classes
serguei.spitsyn at oracle.com
serguei.spitsyn at oracle.com
Wed Sep 3 05:14:49 UTC 2014
Coleen,
It looks good in general.
But I have some questions and minor suggestions below.
||
src/share/vm/oops/instanceKlass.cpp
In the fragment below:
3488 if (!method->on_stack()) {
3489 if (method->is_running_emcp()) {
3490 method->set_running_emcp(false); // no breakpoints for non-running methods
3491 }
3492 } else {
3493 assert (method->is_obsolete() || method->is_running_emcp(),
3494 "emcp method cannot run after emcp bit is cleared");
3495 // RC_TRACE macro has an embedded ResourceMark
3496 RC_TRACE(0x00000200,
3497 ("purge: %s(%s): prev method @%d in version @%d is alive",
3498 method->name()->as_C_string(),
3499 method->signature()->as_C_string(), j, version));
3500 if (method->method_data() != NULL) {
3501 // Clean out any weak method links for running methods
3502 // (also should include not EMCP methods)
3503 method->method_data()->clean_weak_method_links();
3504 }
3505 }
It is not clear to me what happens in the situation when the method is
not running
(both emcp and obsolete cases). Why do we keep such methods, should we
remove them?
Is it because the method_data needs to be collected by the GC first?
If it is so, do we need a comment explaining it?
Another question is about setting is_running_emcp.
Any method after redefinition can be in one of the three states:
method->on_stack() ? 'is_obsolete' or 'is_emcp'
!method->on_stack() ? 'to-be-removed'
I think, the 'is_running_emcp' flag is confusing (a suggestion: use
'is_emcp').
It is not consistent with the 'is_obsolete' flag because we do not spell
'is_running_obsolete'
as non-running obsolete methods hit the category 'to-be-removed'.
Just some thoughts. Sorry for looping around this. :(
A minor suggestion on the following fragment:
3611 if (cp_ref->on_stack()) {
3612 if (emcp_method_count == 0) {
3613 RC_TRACE(0x00000400, ("add: all methods are obsolete; no added EMCP refs"));
3614 } else {
3615 // At least one method is still running, check for EMCP methods
3616 for (int i = 0; i < old_methods->length(); i++) {
3617 Method* old_method = old_methods->at(i);
3618 if (!old_method->is_obsolete() && old_method->on_stack()) {
3619 // if EMCP method (not obsolete) is on the stack, mark as EMCP so that
3620 // we can add breakpoints for it.
3621 old_method->set_running_emcp(true);
3622 RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT, old_method->name_and_sig_as_C_string(), old_method));
3623 } else if (!old_method->is_obsolete()) {
3624 RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT, old_method->name_and_sig_as_C_string(), old_method));
3625 }
3626 }
3627 }
3628
3629 RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
3630 assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
3631 scratch_class->link_previous_versions(previous_versions());
3632 link_previous_versions(scratch_class());
3633 } else {
3634 RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
3635 }
It'd be a simplification to reduce the indent like this:
if (!cp_ref->on_stack()) {
RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
return;
}
if (emcp_method_count == 0) {
RC_TRACE(0x00000400, ("add: all methods are obsolete; no added EMCP refs"));
return;
}
// 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.
old_method->set_running_emcp(true);\
RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
old_method->name_and_sig_as_C_string(), old_method));
} else if (!old_method->is_obsolete()) {
RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
old_method->name_and_sig_as_C_string(), old_method));
}
}
RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
scratch_class->link_previous_versions(previous_versions());
link_previous_versions(scratch_class());
Also, from the 1st round review email exchange...
It'd be nice to add a comment somewhere above to explain this:
> Yes. We set the on_stack bit which causes setting the is_running_emcp bit during safepoints
> for class redefinition and class unloading. After the safepoint, the on_stack bit is cleared.
> After the safepoint, we may also set breakpoints using the is_running_emcp bit.
> If the method has exited we would set a breakpoint in a method that is never reached.> But this shouldn't be noticeable to the programmer.
Thanks,
Serguei
On 9/2/14 5:29 AM, Coleen Phillimore wrote:
>
> Serguei, I didn't answer one of your questions.
>
> On 8/28/14, 5:43 PM, serguei.spitsyn at oracle.com wrote:
>>> This bit is set during purging previous versions when all methods
>>> have been marked on_stack() if found in various places. The bit is
>>> only used for setting breakpoints.
>>
>> I had to ask slightly different.
>> "How precise must be the control of this bit?"
>> Part of this question is the question below about what happens when
>> the method invocation is finished.
>> I realized now that it can impact only setting breakpoints.
>> Suppose, we did not clear the bit in time and then another breakpoint
>> is set.
>> The only bad thing is that this new breakpoint will be useless.
>
> Yes. We set the on_stack bit which causes setting the is_running_emcp
> bit during safepoints for class redefinition and class unloading.
> After the safepoint, the on_stack bit is cleared. After the
> safepoint, we may also set breakpoints using the is_running_emcp bit.
> If the method has exited we would set a breakpoint in a method that is
> never reached. But this shouldn't be noticeable to the programmer.
>
> The method's is_running_emcp bit and maybe metadata would be cleaned
> up the next time we do class unloading at a safepoint.
>
>>
>> But let me look at new webrev first to see if any update is needed here.
>>
>
> Yes, please review this again and let me know if this does what I
> claim it does.
>
> Thank you!
> Coleen
More information about the hotspot-dev
mailing list