[jmm-dev] VarHandle.safepoint() methods

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


On 05/01/17 12:55, Doug Lea wrote:
> On 01/05/2017 04:56 AM, Andrew Haley wrote:
> 
>>> The runtime is free to insert "checkpoint crossing boundaries"
>>> anywhere in code (between any two bytecodes), except where
>>> specifically prohibited by contract.
>>
>> I think I see.  The underlying implementation mechanism would be
>> essentially the same, and would still allow references to be hoisted
>> out of loops, but we have an easier way to describe it in the
>> specification language.
> 
> A complementary approach would be to allow programmers
> to manually insert safepoint checks, such that the JVM would
> not insert one if already there.
> 
> As in  (for some field x, VH X, and local r:)
>      r = X.get(this);
>      ...
>      if (VarHandles.checkPointed()) // returns true if safepoint
>          r = X.getAcquire(this);
> 
> (This is analogous to cases when you manually null-check
> a reference -- the VM does not insert another one.)
> 
> There would need to be some rules and/or a checker tool,
> which seem hard to come up with. But it would at least
> avoid needing to specify a special variant of VH.get,
> which seems even harder.

It's an interesting idea, for sure, but I'm not sure exactly what it
means.  VarHandles.checkPointed() would say if there had been a
checkpoint, but since when?  How would you specify that?

Let's say we have a loop, expanded for clarity.

  for (int i = 0; i < n; i ++) {
    sum += wrappedByteBuf.getSafepoint(vh).get(i);
  }

I'd like the compiler to turn this into

  MappedByteBuffer buf = wrappedByteBuf.getSafepoint(vh);
  for (int i = 0; i < n; i ++) {
    sum += buf.get(i);
  }

and this would naturally be vectorized.

So your form would be

  for (int i = 0; i < n; i ++) {
    MappedByteBuffer buf = wrappedByteBuf.get();
    if (VarHandles.checkPointed()) // returns true if safepoint
       buf = wrappedByteBuf.getAcquire();
    sum += buf.get(i);
  }

I guess a smart compiler could see that VarHandles.checkPointed() will
never be true inside that loop.  And it could decay into

  MappedByteBuffer buf = wrappedByteBuf.get();
  if (VarHandles.checkPointed()) // returns true if safepoint
     buf = wrappedByteBuf.getAcquire();
  for (int i = 0; i < n; i ++) {
    sum += buf.get(i);
  }

I think it'd be easier to specify this in terms of a full fence, like
so:

  if (VarHandles.checkPointed()) // returns true if safepoint
     VarHandles.fullFence();

It'd certainly be easier to implement, and it naturally matches
exactly what a safepoint does.

Andrew.


More information about the jmm-dev mailing list