RFR: 8234426: Sweeper should not CompiledIC::set_to_clean with ICStubs for is_unloading() nmethods
Stefan Karlsson
stefan.karlsson at oracle.com
Mon Dec 2 14:45:16 UTC 2019
Hi Erik,
After discussing this with Erik, I think this looks good. Just to
recapture some of my questions and thoughts:
The nmethod can be in three interesting states when the sweeper executes
this code:
1) is_alive && !is_unloading
2) is_alive && is_unloading
3) !is_alive && is_unloading
The transition from (2) to (3) happens when the GC is unloading the
nmethod concurrently while the sweeper is processing the nmethod. It's
only interesting to bring up state (3), because this is the reason why
we can't assert that the nmethod is_alive.
The interesting transition happens between (1) and (2), and this
transition is well-synchronized between the GC and sweeper by means of
the synchronization protocol in nmethod::is_unloading.
In (1) all oops are good and the nmethod is guaranteed to not be unloaded.
In (2) at least one of the oops are bad and the nmethod is on its way to
become unloaded
The sweeper communicates that it's processing an nmethod by exposing it
to the root set of the threads. We are OK with exposing (1) nmethods,
but we must make sure we never expose (2) nmethods.
The only time the sweeper-processed nmethod is exposed to the root set
of the threads is when we safepoint. The only path that can safepoint in
set_to_clean(bool in_use) is when we're using ICStubs. However, we don't
need to use ICStubs when an nmethod is not "in use". is_unloading
nmethods (2) are not "in use", otherwise they would have been found by
root scanning and/or entry barriers and would have stayed !is_unloading.
Therefore the code was changed to set_to_clean(!is_unloading()).
Thanks,
StefanK
On 2019-11-22 11:49, erik.osterlund at oracle.com wrote:
> Hi,
>
> When the sweeper processes an nmethod, it will clean inline caches if
> it is_alive().
> Today, the cleaning will utilize transitional states (using ICStubs)
> if the nmethod is_alive(),
> which is always true for the sweeper. If it runs out of ICStubs, it
> might have to safepoint
> to refill them. When it does, the currently processed nmethod might be
> is_unloading().
> That is not a problem for the GC per se (safepoint operation fusing
> with mark end), but it
> is a problem for heap walkers that get confused that an nmethod
> reachable from a thread is unloading
> and hence has dead oops in it. This sweeper nmethod is the *only*
> nmethod that violates an
> invariant that nmethods reachable from threads (Thread::nmethods_do)
> are not unloading.
>
> By simply changing the condition to not use ICStubs when the nmethod
> is_unloading(), we
> get this neat invariant, and code gets less confused about this.
>
> Bug:
> https://bugs.openjdk.java.net/browse/JDK-8234426
>
> Webrev:
> http://cr.openjdk.java.net/~eosterlund/8234426/webrev.00/
>
> Thanks,
> /Erik
More information about the hotspot-dev
mailing list