RFR: 8194312: Support parallel and concurrent JNI global handle processing
Erik Österlund
erik.osterlund at oracle.com
Wed Jan 10 13:50:04 UTC 2018
Hi Kim,
I have already seen earlier incarnations of this code so I only have a
few comments regarding things that were not in that incarnation.
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OopStorage.java:
The Java implementation of OopStorage for the SA agent seems a bit empty
and full of TODO comments to actually implement something. It seems like
quite a bit of the other changes to the SA assumes that this actually
does something. For example there are changes to use OopStorage oopsDo
instead of JNIHandleBlock oopsDo, which I presume means there has to be
some oopsDo implementation in place for OopStorage.
Is the intention to implement that later on in a separate RFE?
src/hotspot/share/gc/shared/oopStorage.hpp:
The OopStorage::oops_do functions accept some kind of OopClosure and
performs iteration with it. I'm curious though why it takes the specific
type of OopClosure as a template parameter, passes it around, and
eventually discards the information without making use of it? I was
thinking perhaps the intention was to use the closure type information
to devirtualize the do_oop() call, but that does not appear to be the
case. To do that you would have to in OopStorage::OopFn::operator()()
perform a qualified _cl->Closure::do_oop() call instead of _cl->do_oop()
(and possibly take some care to prevent abstract oop closure types like
OopClosure or ExtendedOopClosure from being devirtualized, which would
be awkward (doable with some EnableIf<!IsSame<Closure,
OopClosure>::value>::type overload, or something like that).
In other words, it seems like either this template parameter is
unnecessary and you could just replace uses of it with OopClosure, or it
should be made useful, e.g. by devirtualizing the calls or something.
Same goes for the IsAliveClosure parameter for weak_oops_do.
src/hotspot/share/gc/shared/oopStorage.cpp:
I recall in the pre-review we had some discussion about whether the
infrastructure for supporting early iteration termination was necessary
or not. You had me convinced that JNI would need it for something. Is
this still the case, or has that use case been revised? Reading through
the new JNI code, I could not find uses of
OopStorage::iterate_safepoint() from the JNI code, and hence no uses of
early termination. Having said that, it does look rather simple now with
only the sequential case supporting early termination.
However, if there is indeed no use any longer for OopStorage::iterate()
and hence the only publicly available tool for early iteration exit, I
wonder if perhaps it should be reconsidered if we want to remove that
infrastructure. Or will there be other use cases down the road?
Currently I find it at least a bit confusing that, e.g.
OopStorage::iterate_safepoint() expects a function of type F that
returns bool while OopStorage::BasicParState::iterate() expects a
function of type F that returns void. For the
OopStorage::iterate_safepoint() case it is clearly described in the
documentation, in the OopStorage::BasicParState::iterate() case I did
not find it clear that this F is a different F to the safepoint one.
I guess I propose either removing early termination support alltogether
if nobody is using it anyway (and hence having the F function type
consistently return void), or documenting clearly that the sequential
and parallel iteration functions expect different function types - one
with bool return type and one with void return type, depending on
whether early termination is supported or not.
Apart from the above minor remarks, I am delighted to see these changes.
I am extra delighted to see deleted_handle() disappear. I am also
delighted to see the new simplified synchronization for parallel
iteration - that worked out nicely. Thank you for building a good oop
storage solution.
Thanks,
/Erik
On 2018-01-02 22:41, Kim Barrett wrote:
> Please review this change to the implementation of JNI global and weak
> global handles, providing infrastructure for parallel and concurrent
> processing of such handles.
>
> This change introduces OopStorage, a data structure for managing
> off-heap references to objects allocated in the Java heap. JNI global
> and weak global handles are reimplemented using OopStorage, rather
> than using JNIHandleBlock. (JNI local handles continue to use
> JNIHandleBlock; the lifetime management and concurrency issues are
> very different for local vs global handles.)
>
> This change does not change any GCs to use the new parallel and
> concurrent capabilities, only laying the foundations for doing so.
>
> Other uses of OopStorage are also being considered, in the context of
> runtime latency improvements for ZGC and other collectors. The idea is
> to change some (often weak) oop references in runtime data structures
> to OopStorage-managed handles, simplifying the GC processing and
> avoiding (potentially concurrent) GC walks of runtime data structures.
>
> As a side effect, this enhancement fixes these bugs:
> 8174790: Race adding (weak) global JNI handles and determining type of handle
> 8176454: Performance: jweak references not suitable for robust cache architecture
>
> Some things not addressed by this change include:
>
> - 8194309: JNI handle allocation failure not reported correctly
> For now, the pre-existing vm_exit_out_of_memory behavior is retained.
>
> - Updating JNIHandles to use the new Access protocol.
>
> - Serviceability Agent updates for OopStorage and JNI usage. Just
> enough has been done to allow existing SA tests to "pass". This will
> be addressed as a followup.
>
> CR:
> https://bugs.openjdk.java.net/browse/JDK-8194312
>
> Webrev:
> http://cr.openjdk.java.net/~kbarrett/8194312/open.00/
>
> Testing:
> Mach5 hs-tier1 through hs-tier5, jdk-nightly
>
More information about the hotspot-dev
mailing list