RFR(M) 8176100: [REDO][REDO] G1 Needs pre barrier on dereference of weak JNI handles

Mikael Gerdin mikael.gerdin at oracle.com
Tue Mar 14 13:11:21 UTC 2017


Here we go again...
This time around the fix is exactly the same but since I changed the 
lock ranks in 8176363 we shouldn't be hitting any lock ordering assertions.


Hi all,
Please review this revised change to jweak to support G1.

I've copied Kim's original description of the fix below for reference:

 >
 > The problem being addressed is that, when using G1, dereferencing a
 > jweak must ensure the obtained referent is ensured live, just as for
 > other weak reference types.  This has always been a requirement, and
 > failure to do so appears to be a since-day1 G1 bug.
 >
 > There are two categories of places that need to address this issue:
 > JNIHandles::resolve and friends, and returning a jobject from native
 > code to Java.  In both of these places the jobject whose contained oop
 > is being extracted might really be a jweak.  jweak is
 > representationally indistinguishable from jobject; jweak is just a
 > typedef for jobject.  The documentation says a jweak can be used
 > anywhere a jobject is permitted, making that type equivalence
 > necessary for a C API.  (A C++ API might be able to have distinct
 > types via inheritance, though would still need a method for
 > distinguishing them at runtime.  But since JNI is a C API...).
 >
 > The basic approach being taken is to "tag" jweaks by setting the low
 > order bit (recall that jweak == jobject == _jobject*), in order to
 > distinguish them from non-jweak jobjects.  This tagging is only being
 > done when the selected GC needs the distinction, e.g. G1.  This gives
 > us a representational difference between jobject and jweak on which to
 > base the different behavior, hiding that distinction behind the
 > existing API.
 >
 > JNIHandles::resolve and friends are changed to unconditionally strip
 > off any potential weak tag when translating from jobject to to oop*.
 > That's cheaper than testing for the conditional use of tagging and
 > then stripping.  Also stripped when deleting JNI handles.
 >
 > TemplateInterpreterGenerator::generate_native_entry and
 > SharedRuntime::generate_native_wrapper are changed to conditionally
 > emit code to apply the G1 pre-barrier to the value obtained from a
 > jobject result, when the result is tagged as a jweak, which only
 > occurs when using G1.
 >
 > For arm32/arm64, this required moving the g1_write_barrier_pre
 > definitions from InterpreterMacroAssembler to MacroAssembler.  Also
 > moved g1_write_barrier_post, for consistency.
 >

In addition to Kim's final version of the change (which was backed out) 
this updated version adds code to mask out the weak tag bit in the fast 
JNI field getters on all platforms where fast JNI getters are used.

Since the fast JNI getters only read primitive values from objects me 
and Kim decided that there was no need to invoke the G1 pre-barrier if a 
jweak was used as the "receiver" for the getters, this simplifies the 
change to the fast getters and I was able to come up with a seemingly 
efficient instruction encoding on all platforms.

A couple of comments about the implementations:
My goal was to encode clearing of the weak_tag_mask (which at the moment 
is 1).
On SPARC and 32 bit arm there is an instruction that can be used 
straight off to perform an and with a value that is first negated, ANDN 
on SPARC and BTC on ARM.
On 64 bit ARM the encoding for immediates allows encoding of the bitwise 
inverse of 1 (0xfffffffffffffffe) but if weak_tag_mask is changed the 
encoding may fail.
On x86 I pass the mask as a signed 32 bit immediate but note that the 
assembler encodes it as an 8 bit immediate and sets a sign-extension bit 
in the opcode.


Testing:
Standard JPRT and tier2-3 HotSpot tests.
I've modified the CallWithJNIWeak test to call all the primitive getters 
and some other interesting cases I came up with.
I've also run the CallWithJNIWeak test on all platforms on both product 
and fastdebug builds (since fast JNI getters are implicitly disabled in 
debug builds due to VerifyJNIFields being enabled by default in debug 
builds.

The aarch64 change has been tested in the previous round of this change.

Full webrev:
http://cr.openjdk.java.net/~mgerdin/8176100/webrev.0/

Bugs:
https://bugs.openjdk.java.net/browse/JDK-8176100
https://bugs.openjdk.java.net/browse/JDK-8175085
https://bugs.openjdk.java.net/browse/JDK-8166188

Thanks
/Mikael


More information about the hotspot-dev mailing list