[jmm-dev] VarHandle.safepoint() methods

Andrew Haley aph at redhat.com
Thu Jan 5 09:35:18 UTC 2017

On 04/01/17 21:47, David Holmes wrote:
> Hi Andrew,
> On 5/01/2017 4:04 AM, Andrew Haley wrote:
>> This is a proposal for a new VarHandle method, but it also is an
>> extension to the Java Memory Model, so I'm starting the discussion
>> here.
>> My intention is to provide an efficient way to handle the case where a
>> field has reads which outnumber writes by several orders of magnitude.
>> Once a field has been successfully modified, no thread may observe a
>> stale value.  Writes to a field are expected to be very rare, and can
>> be expensive.
>> It provides a secure and fast way to do something like a volatile
>> access but without any memory fences (or even any restrictions on
>> memory reordering) on the reader side.
>> I propose two new VarHandle methods:
>> Object getSafepoint()
>>   Returns the value of a variable, with memory semantics of reading as
>>   if the variable was declared non-volatile, except that this load
>>   shall not be reordered with a preceding safepoint.
> I'm no compiler guy but I would think, given the compiler has no idea 
> what may lead to a safepoint, that this would have to preclude any 
> reordering of any kind around the load.

We have a pretty good idea what needs to be done to the compiler to
make this work.  It's not easy, but neither is it impossible.

>> static void safepoint()
>>   Wait for a safepoint.  When this method returns, every thread in the
>>   JVM shall have executed a safepoint.  Ensures that loads and stores
>>   before the safepoint will not be reordered with loads and stores
>>   after the safepoint.
>> [Note that VarHandle.safepoint() does not specify whether the VM
>> safepoints immediately or the thread waits for a safepoint which would
>> occur anyway.]
> So you're relying on the existence of a global synchronization point 
> (aka "safepoint") in the VM and then using that to achieve "global 
> synchronization" without having to do any work in the common case.


> As an API I find that somewhat ill-defined. I would not want to see VM 
> safepoints enshrined in a user-level API. Nor would I want to see a 
> distinct global synchronization mechanism.

Well, the global synchronization mechanism exists already in most
JVMs, and there's not much chance of it going away.  All this does
is expose it.

> In terms of implementation the existing VM safepoint mechanism has no 
> means to "wait for a safepoint", but could trivially request one. I'll 
> also note that we're always looking at ways to remove the need for 
> global safepoints in the VM, so a request may be essential - though when 
> using GuaranteedSafepointInterval a sleep of that duration would ensure 
> a global safepoint has occurred.

Sure.  I was thinking of a version of VarHandle.safepoint() which took a
timeout: if a safepoint didn't arrive after N seconds, force one.

>> A mechanism like this is needed in order to implement
>> MappedByteBuffer.unmap() securely and efficiently, but I think this
>> mechanism is sufficiently useful that it should be exposed as an API.
> I'm unclear how you deal with detecting the buffer has been unmapped 
> since the call to buf() in buf().get() ? Are you also requiring that no 
> safepoint can occur in that interval?

Yes, exactly.  The compiler knows that there is no safepoint in that

>> From an implementation point of view, getSafepoint() is a plain read
>> except that a JIT compiler cannot reorder it with a safepoint.
>> getSafepoint() can be hoisted out of loops and doesn't inhibit
>> vectorization, so the overhead of getSafepoint() can be made extremely
>> low, and hopefully almost zero.
> How does a JIT know what may lead to a safepoint?

I don't know what you mean by this question.  It already knows this.

> How can you hoist out of a loop if there is a safepoint check on
> each loop iteration?

You can't, but not all loops have safepoints.


More information about the jmm-dev mailing list