RFR: 8210498: nmethod entry barriers

Erik Österlund erik.osterlund at oracle.com
Fri Oct 5 15:07:04 UTC 2018


Hi,

In order to implement concurrent class unloading for ZGC, a mechanism 
will be required to arm nmethods in a safepoint such that the first 
entry into an nmethod after the pause triggers a barrier before continuing.

The barrier will be used for:
   * Patching immediate oops, and keeping phantomly reachable oops alive 
through the nmethod entry
   * Catching calls from stale IC caches (due to class unloading) into 
nmethods that are being unloaded (containing broken oops and metadata), 
and lazily clean the IC cache and re-resolve the call.

This implementation is for x86_64 and is based on the prototyping work 
of Rickard Bäckman. So big thanks to Rickard, who will co-author of this 
patch.
The way it works is that there is a cmp #offset(r15_thread), 
simm32_epoch); je #continuation; inserted into the verified entry of 
nmethods that conditionally calls a stub trampolining into the VM.
When the simm32_epoch is not equal to some TLS-local field, then a slow 
path is taken to run some barrier inside of the VM.
By changing this TLS-local field in the safepoint, all verified entries 
will take the slow path into the VM when run, where the barrier is 
eventually disarmed by patching the simm32_epoch value of the 
instruction stream to the current globally correct value.

In terms of abstractions, to utilize this mechanism, you need to create 
your BarierSet with an BarrierSetNMethod helper object, just like the 
BarrierSetAssembler, BarrierSetC1 and BarrierSetC2. The 
BarrierSetNMethod base class handles the barrier itself. It has a 
virtual function, nmethod_entry_barrier, which gets called by the slow 
paths. So each user of this mechanism inherits from BarrierSetNMethod 
and puts its barrier in there.

The OSR nmethods do not have a verified entry. Therefore, the barrier is 
run explicitly in the runtime before calling into OSR nmethods to 
achieve the same effect of trapping new calls into nmethods.

The nmethod entry barrier returns true/false depending on whether the 
called nmethod may be entered or not. This allows lazily cleaning 
nmethod IC caches during unloading, which invokes the same helper method 
that is patched into the verified entry when made not entrant.

Eventually, I would like to also use this mechanism to remove the 
nmethod hotness counter maintenance we today perform in safepoint 
cleanup instead. These nmethod entry barriers can provide better 
heuristics for whether nmethods are used or not. But that would require 
buy-in from maintainers of other platforms. So let's take one step at a 
time.

For the curious reader thinking that this might be an expensive 
operation, it is not. This check in the nmethod verified entry is very 
predictable and cheap. And because of use of inlining, the checks become 
more infrequent. In my evaluation, it has gone completely under the 
radar in benchmarking (running this with my current version of 
concurrent class unloading in ZGC).

Webrev:
http://cr.openjdk.java.net/~eosterlund/8210498/webrev.00/

Bug ID:
https://bugs.openjdk.java.net/browse/JDK-8210498

Thanks,
/Erik


More information about the hotspot-dev mailing list