RFR 8165246: [REDO] InstanceKlass::_previous_version_count goes negative
Daniel D. Daugherty
daniel.daugherty at oracle.com
Wed Sep 7 15:36:49 UTC 2016
On 9/6/16 10:24 AM, Coleen Phillimore wrote:
> Summary: make _has_previous_version a boolean that is set to true when
> previous version of a class is added or during class unloading call to
> purge_previous_versions
>
> The failed fix was because InstanceKlass's previous_versions klasses
> were walked more than once during class unloading, because the scratch
> classes are also on the CLD::_klasses list. This change does three
> things. 1. Only walk the class if has_been_redefined (which is not
> set for the scratch class), 2. set next link to NULL for the scratch
> class when removed from the previous version list, and 3. change the
> counter to a flag because the counter may never go to zero if a CLD
> has redefined classes with previous versions and is unloaded. For
> this latter case we don't need to walk previous_versions.
>
> I tested this with changes 1 and 2 in Kitchensink, to verify the
> diagnosis, and then added 3 and retested.
> Also tested with the fix for
> https://bugs.openjdk.java.net/browse/JDK-8156137 which was checked
> into hs_-omp repository.
>
> Also ran through RBT 4 tiers nightly tests.
>
> open webrev at http://cr.openjdk.java.net/~coleenp/8165246.01/webrev
src/share/vm/oops/instanceKlass.hpp
No comments.
src/share/vm/oops/instanceKlass.cpp
L3370: // Globally, there is at least one previous version of a
class to walk
L3371: // during class unloading, which is saved because there are
old methods in the class
L3372: // are still running. Otherwise the previous version list
is cleaned up.
Perhaps a little tweaking of the comment:
// Globally, there is at least one previous version of the
class to walk
// during class unloading, which was saved because there
were old methods
// in the class that are still running. Otherwise the
previous version
// list is cleaned up.
L3375: // Returns whether there are previous versions of a class
for class
L3376: // unloading only. This resets the value to false.
purge_previous_versions
L3377: // will set it to true if there are any left, i.e. if
there's any work to do for
L3378: // next time. This is to avoid the expensive code cache
walk in CLDG::do_unloading.
Perhaps a little tweaking of the comment:
// Returns true if there are previous versions of a class
for class
// unloading only. Also resets the flag to false.
purge_previous_versions
// will set the flag to true if there are any left, i.e., if
there's any
// work to do for next time. This is to avoid the expensive
code cache
// walk in CLDG::do_unloading().
L3379: bool InstanceKlass::has_previous_versions() {
L3383: _has_previous_versions = false;
Named like a query function, but it has a side effect.
Perhaps: has_previous_versions_and_reset()?
L3391: assert (has_been_redefined(), "Should only be called for
main class");
Nit: please delete the space before '('.
L3427: loader_data->add_to_deallocate_list(pv_node);
L3428: InstanceKlass* next = pv_node->previous_versions();
L3429: pv_node->link_previous_versions(NULL); // point
next to NULL
L3430: last->link_previous_versions(next);
The pv_node to be deleted is added to the deallocate list
before it is decoupled from chain. Perhaps it should be
added after it is decoupled to permit parallel processing
of the deallocate list, i.e., move L3427 after L3430. I
don't think it is processed in parallel now, but down the
road...
L3592: // Add previous version if any methods are still running.
L3593: _has_previous_versions = true;
In the other place you set the flag to true, you mention
that this is for class unloading. Do you want to say that
here also?
test/runtime/RedefineTests/RedefinePreviousVersions.java
L26: * @bug 8164692
Please change the bug ID to 8165246.
L27: * @summary Redefine previous_versions count goes negative
Need to update the test summary.
L88: // previous_version_list and the count should stay
zero and not go negative
Need to update the comment since there is no longer
a counter.
OK so the whole reason for InstanceKlass::has_previous_versions() is
an optimization so that we don't have to do an expensive code cache
walk for previous versions during class unloading. The old code
implemented the "state of having a previous version" as a counter.
The new code implements the "state of having a previous version"
as a flag that is only set when we add a previous version (yea!)
and cleared when it is queried. Since there is no more counter,
we won't run into the bug we're trying to fix.
The only thing that bugs me is this:
bool v1 = has_previous_versions();
bool v2 = has_previous_versions();
I would expect (v1 == v2) which isn't what you get.
Perhaps renaming from has_previous_versions() to
has_previous_versions_and_reset() will make it clear
that there is a side effect...
Dan
> bug link https://bugs.openjdk.java.net/browse/JDK-8165246
>
> Thanks,
> Coleen
>
>
More information about the hotspot-runtime-dev
mailing list