[9] RFR (M): 8139595: MethodHandles::remove_dependent_nmethod is not MT safe

John Rose john.r.rose at oracle.com
Tue Nov 10 02:37:18 UTC 2015


I think this expression occurs too many times:
  DependencyContext dep_context(&_dep_context);

It would look better if factored into an access method:
  inline DependencyContext InstanceKlass::dependencies() {
    DependencyContext dep_context(&_dep_context);
    return dep_context;
  }

That way the raw machine word InstanceKlass::_dep_context can be isolated.
CallSiteContext::vmdependencies already does the corresponding move for CallSite.
(I understand that you don't want to make ik.hpp depend on dc.hpp.
Just put forward declarations of Deps and IK::deps in ik.hpp.)

Mild suggestion:  Add a constructor parameter to capture the base oop (of the callsite, or null for the IK).
Use it only in debug mode to check for GC changes.  Or sample a global GC or safepoint count.
The point is that the lifetime of the Deps object should not extend beyond the next safepoint.

I agree with Coleen:  This is a good refactor.

Reviewed.

— John

On Nov 6, 2015, at 5:03 AM, Vladimir Ivanov <vladimir.x.ivanov at oracle.com> wrote:
> 
> Thanks, Coleen!
> 
> Updated version:
>  http://cr.openjdk.java.net/~vlivanov/8139595/webrev.02/
> 
>> I think DependencyContext is big enough to be a new file, and not be
>> added to instanceKlass.hpp.  There are too many unrelated things in
>> instanceKlass.
> Agree. Moved it to src/share/vm/code/dependencyContext.[ch]pp
> 
>> The hidden bit stuff is ok in InstanceKlass.  Does
>> has_unloaded_dependent accessed concurrently like
>> _is_marked_dependent?
> Good point. DependencyContext::remove_dependent_nmethod should set has_stale_entries in a thread safe manner (added Atomic::xchg_ptr call).
> It is not needed when the flag is cleared.
> 
>> It would be nice to move _is_marked_dependent
>> field also to encapsulate it but that would ruin your bit packing.
> There's a spare bit to use, but I think _is_marked_dependent is specific to InstanceKlass and should remain there. It doesn't have any meaning for CallSite dependencies.
> 
>> Also, since you have changes to vmStructs, do you have duplicate changes
>> to make to the serviceability agent code?  Are there duplicate changes
>> for the jvmci code?
> I haven't found any mentions of _has_unloaded_dependent or _dependencies fields in SA or JVMCI code. Do you think it is an overlook on SA side and I should add it?
> 
> Best regards,
> Vladimir Ivanov
> 
>> 
>> Thanks,
>> Coleen
>> 
>> On 11/5/15 1:54 PM, Vladimir Ivanov wrote:
>>> Updated version:
>>> http://cr.openjdk.java.net/~vlivanov/8139595/webrev.01/
>>> 
>>> In addition to name polishing and encapsulating purging logic in
>>> {add|remove}_dependent_nmethod methods, I got rid of
>>> DependencyContext::wipe() method and added "friend class
>>> TestDependencyContext" declaration (noticed such practice in other
>>> cases when tests need access to tested class internals).
>>> 
>>> Best regards,
>>> Vladimir Ivanov
>>> 
>>> On 11/5/15 7:46 PM, Aleksey Shipilev wrote:
>>>> On 11/05/2015 04:54 PM, Vladimir Ivanov wrote:
>>>>> Regarding internal purging, add_dependent_methods doesn't iterate over
>>>>> the whole list, but looks for the relevant entry. It means that "purge"
>>>>> flag should force full iteration. I think that keeping them separately
>>>>> (add_dependent_methods() vs purge()) looks cleaner.
>>>> 
>>>> I think it is better to encapsulate the "piggybacking" behavior within
>>>> the DependencyContext itself, because that seems to be a
>>>> general/expected feature of DependencyContext class. It is weird to ask
>>>> class users to spell it out specifically.
>>>> 
>>>> 
>>>>> I could add "purge" flag and move the following code into
>>>>> add_dependent_methods:
>>>>> void DependencyContext::add_dependent_nmethod(nmethod* nm, bool
>>>>> do_purge
>>>>> = false) {
>>>>>    ...
>>>>>    if (has_unloaded_dependent() && do_purge) {
>>>>>      purge();
>>>>>    }
>>>>> }
>>>>> 
>>>>> Is it what you are suggesting?
>>>> 
>>>> Yes.
>>>> 
>>>> 
>>>>>>   * DependencyContext now has three methods: purge(), clear(),
>>>>>> wipe(). I
>>>>>> have trouble understanding which method does what!
>>>> 
>>>>> There are basically 2 operations needed:
>>>>>   * purge(): only remove stale entries; no additional work is
>>>>> performed;
>>>> 
>>>> Oh. Should probably mention "stale" in the name. See e.g. Java-ish:
>>>>  WeakHashMap.expungeStaleEntries()
>>>>  ThreadLocal.expungeStaleEntries()
>>>>  WeakCache.expungeStaleEntries()
>>>> 
>>>> 
>>>>> wipe() is only for unit-testing purposes (see TestNmethodBucket): it
>>>>> just deallocates all nmethodBucket entries without touching
>>>>> nmethods. It
>>>>> is necessary since nmethod pointers are faked by the test.
>>>> 
>>>> Okay. Is there a convention how you should name the test-related methods
>>>> like these? I would expect something like debug_deallocate_buckets().
>>>> 
>>>> Thanks,
>>>> -Aleksey
>>>> 
>>>> 
>> 



More information about the hotspot-dev mailing list