RFR: 8213755: Let nmethods be is_unloading() outside of safepoints
Erik Österlund
erik.osterlund at oracle.com
Tue Nov 20 16:27:16 UTC 2018
Hi Coleen,
Will remove the constructor before pushing.
Thanks for the review.
/Erik
On 2018-11-20 17:22, coleen.phillimore at oracle.com wrote:
>
>
> On 11/20/18 11:04 AM, Erik Österlund wrote:
>> Hi Coleen,
>>
>> Thanks for the review.
>>
>> On 2018-11-19 23:42, coleen.phillimore at oracle.com wrote:
>>>
>>>
>>> On 11/19/18 7:31 AM, Erik Österlund wrote:
>>>> Hi Coleen,
>>>>
>>>> Thanks for having a look at this.
>>>>
>>>> New full webrev:
>>>> http://cr.openjdk.java.net/~eosterlund/8213755/webrev.01/
>>>>
>>>> Incremental:
>>>> http://cr.openjdk.java.net/~eosterlund/8213755/webrev.00_01/
>>>>
>>>> On 2018-11-17 00:21, coleen.phillimore at oracle.com wrote:
>>>>>
>>>>> How about instead of two bool arguments that are hard to read and
>>>>> error prone and need comments, like:
>>>>>
>>>>> 76 CompiledMethodIterator iter(true /* only_alive */, false /*
>>>>> only_not_unloading */);
>>>>>
>>>>>
>>>>> enum FilterAlive { all_blobs, only_alive };
>>>>> enum FilterUnloading { all_blobs, only_not_unloading };
>>>>>
>>>>> Then it can be something like:
>>>>>
>>>>> CompiledMethodIterator iter(only_alive, all_blobs);
>>>>>
>>>>> Don't know if you can repeate all_blobs like that.
>>>>
>>>> You can't really have all_blobs in both. I tried out a variant with
>>>> a single enum though, hope you like it.
>>>> The observation was that we only need 3 different variations:
>>>> all_blobs, only_alive or only_alive_and_not_unloading. So I made an
>>>> enum out of that.
>>>> In fact, these three modes are the only ones I support right now,
>>>> so they are also the only valid options, which made the single enum
>>>> look even more reasonable.
>>>
>>> I do like it!
>>>>
>>>>> http://cr.openjdk.java.net/~eosterlund/8213755/webrev.00/src/hotspot/share/code/codeCache.cpp.frames.html
>>>>>
>>>>>
>>>>> I'm not sure if metadata_do() should filter out unloading. It's
>>>>> looking for "old" methods to stop from deallocating memory for
>>>>> them (but it's in a safepoint). If you're unloading, the IC caches
>>>>> are already cleaned out?
>>>>
>>>> IC caches to unloading nmethods are not necessarily cleaned out.
>>>> The concurrent GC threads will clean the IC caches concurrently,
>>>> but a JavaThread can call the IC cache before the GC has gotten
>>>> around to cleaning the IC cache. But any such call into an
>>>> is_unloading() nmethod will be trapped by nmethod entry barriers,
>>>> which will call the IC miss handler, which sorts things out lazily.
>>>> So you can view this as the IC caches to is_unloading() nmethods
>>>> being logically cleared, but not necessarily physically cleared
>>>> yet. The effect is the same - the is_unloading() nmethods may not
>>>> be entered from anywhere, including IC caches.
>>>>
>>>> So if you were to not filter is_unloading(), you would get a whole
>>>> bunch of nmethods that are not really reachable by the application,
>>>> i.e. they are not on any stacks, and may not be entered by the
>>>> application. Therefore, I think it's perfectly fine to filter them
>>>> out here, unless I missed something. And this makes the behaviour
>>>> closer to as-if the nmethods were indeed unloaded in the safepoint.
>>>
>>> Ok. The thing I'm worried about is if we deallocate memory for a
>>> Method* in the is_unloading methods, and some other cleaning or
>>> sweeping thread tries to access that memory. This is used by
>>> MetadataOnStackMark during safepoints to see what's safe to
>>> deallocate from redefinition.
>>
>> I understand. I do think this is safe though, and it only walked
>> is_alive() compiled methods looking for metadata before, e.g. not
>> unloaded or zombie methods. Similarly, nobody should be poking around
>> at the metadata of unloading methods. Should being the key word there
>> I guess...
>>
>>>
>>>>
>>>>> http://cr.openjdk.java.net/~eosterlund/8213755/webrev.00/src/hotspot/share/code/nmethod.cpp.frames.html
>>>>>
>>>>>
>>>>> 1108 // The release is only needed for compile-time ordering, as
>>>>> accesses
>>>>> 1109 // into the nmethod after the store is not safe, due to the
>>>>> sweeper
>>>>> 1110 // being allowed to free it then, in the case of concurrent
>>>>> nmethod
>>>>> 1111 // unloading. Therefore, there is no need for acquire on the
>>>>> loader side.
>>>>> 1112 OrderAccess::release_store(&_state, (signed char)unloaded);
>>>>>
>>>>> I tried to make sense out of this first sentence, but couldn't
>>>>> really. After the store to unloaded, can the sweeper free the
>>>>> nmethod? maybe remove "then, " and it would make more sense?
>>>>
>>>> Right, after the store is observed, the sweeper thread may
>>>> concurrently observe the nmethod to be unloaded, and then it may
>>>> immediately flip it over to zombie. And I don't want any concurrent
>>>> make_unloaded code in that nmethod to still be racing after the
>>>> sweeper turns it into zombie; a very unnecessary race to deal with.
>>>>
>>>> I updated the comment - hopefully it reads better now.
>>>>
>>>
>>> How about removing a comma changing it to accesses are not safe, or
>>> access is not safe.
>>> + // The release is only needed for compile-time ordering, as accesses
>>> + // into the nmethod after the store are not safe, due to the sweeper
>>> + // being allowed to free it when the store is observed during
>>> + // concurrent nmethod unloading. Therefore, there is no need for
>>> + // acquire on the loader side.
>>
>> Comma will be removed before pushing.
>>
>>> http://cr.openjdk.java.net/~eosterlund/8213755/webrev.01/src/hotspot/share/code/codeCache.hpp.udiff.html
>>>
>>> Why is this copy constructor defined? Isn't this what the default
>>> copy constructor would do?
>>
>> Yeah it is. I like explicitly typing out what constructors should do.
>> But I can remove it if you prefer that.
>
> Can you remove it? It's confusing there since we don't generally have
> default constructors typed out, one has to study it to see that it's a
> default copy constructor. Then ask myself why is it there.
>
> I don't need to see another webrev.
>
> Thanks,
> Coleen
>>
>>> It looks almost perfect to me :)
>>
>> Awesome. Thanks for reviewing this.
>>
>> Thanks,
>> /Erik
>>
>>> Coleen
>>>
>>>> Thanks,
>>>> /Erik
>>>>
>>>>> Thanks,
>>>>> Coleen
>>>>>
>>>>> On 11/12/18 5:46 PM, Erik Österlund wrote:
>>>>>> ..put in bug number in subject to make mail filters happy.
>>>>>>
>>>>>> /Erik
>>>>>>
>>>>>> On 2018-11-12 23:44, Erik Österlund wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> All current GCs perform code cache unloading in safepoints.
>>>>>>> Therefore, nmethods that are alive but is_unloading() are never
>>>>>>> observed outside of safepoints. With concurrent class unloading,
>>>>>>> nmethods that are alive but is_unloading() will become
>>>>>>> observable outside of safepoints. This must be handled
>>>>>>> appropriately.
>>>>>>>
>>>>>>> In this patch I changed the nmethod/compiled method iterators to
>>>>>>> accept parameters describing whether they should filter out not
>>>>>>> is_alive() or is_unloading() methods. Since there is no obvious
>>>>>>> default (all combinations are used depending on call site), you
>>>>>>> have to explicitly set what iteration mode you want.
>>>>>>>
>>>>>>> Other than that, I make sure that the sweeper stays away from
>>>>>>> is_unloading() nmethods that are not yet is_unloaded(). To make
>>>>>>> the interactions between the sweeper and concurrent GC threads
>>>>>>> safe, I had to move down the store that sets the state to
>>>>>>> unloaded, and use a release_store there, to make sure no
>>>>>>> accesses float below it at compile-time. Once that store is
>>>>>>> observed, nmethods may be deleted.
>>>>>>>
>>>>>>> In the IC miss handler, I also need to lazily clean stale IC
>>>>>>> caches due to calling is_unloading nmethods using nmethod entry
>>>>>>> barriers.
>>>>>>>
>>>>>>> Webrev:
>>>>>>> http://cr.openjdk.java.net/~eosterlund/8213755/webrev.00/
>>>>>>>
>>>>>>> Bug:
>>>>>>> https://bugs.openjdk.java.net/browse/JDK-8213755
>>>>>>>
>>>>>>> Thanks,
>>>>>>> /Erik
>>>>>
>>>>
>>>
>>
>
More information about the hotspot-dev
mailing list