Update to description of JEP 193: Enhanced Volatiles

Remi Forax forax at univ-mlv.fr
Thu Oct 30 19:58:12 UTC 2014


On 10/30/2014 04:53 PM, Paul Sandoz wrote:
> On Oct 30, 2014, at 4:47 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>> On 10/30/2014 03:02 PM, Paul Sandoz wrote:
>>> Hi,
>>>
>>> I have, with the help of Brian, Doug and John, updated the description of JEP 193: Enhanced Volatiles to reflect our current thinking based on:
>>>
>>> - the prototype implementation in valhalla;
>>> - performance measurements of that implementation; and
>>> - investigations related to signature polymorphic methods and invokedynamic.
>>>
>>> Thanks,
>>> Paul.
>> I seems that the changes are not propagated to the JEP yet,
>> but there are available throught the corresponding bug:
>>   https://bugs.openjdk.java.net/browse/JDK-8046183
>>
> Doh! thanks, i forgot to send the link out,
> Paul,

Here is a kind of counter-proposal because I think that there is a far 
simpler and more secure API.

I think that instead of having to first instantiate an object 
(VarHandle) and then call a method on it,
this can be done in one method.

|public  class  Safe  {
     @Intrinsic
      public  staticObject  get(Object receiver, String fieldName) { }|
||     @Intrinsic
      public  staticObject  getRelaxed(Object receiver, String fieldName) { }|
     ||||@Intrinsic||
     ||||public  staticObject  getAcquire(Object receiver, String fieldName) { }|||
||||||     @Intrinsic|||
     ||||public  staticObject  getRelaxed(Object receiver, String fieldName) { }|||
|||||     @Intrinsic||||
     ||||public  staticObject  |||||||getSequential|(Object receiver, String fieldName) { }||
|
||||||     @Intrinsic|||||
     |||public  static  void  set(|||||||Object receiver, String fieldName|||, Object value) { }|
     // and all other related variations
     
   ...        
}|

and this is how to use it:

class  Foo  {

|    int i;

     public void acquire() {
      |||boolean  r=  (boolean)Safe.compareAndSet(this, "i",  0,  1);
      ...
|    }
}|


At compile time, the compiler checks that a method Safe.compareAndSet 
with compatible parameter types exists
but instead of generating an invokestatic, it generates an invokedynamic 
which uses the signature of the actual callsite.
Using the actual types in the signature allows to avoid unnecessary 
boxing while
keeping the typechecking rules simples (they are not changed !) as 
explained in the current draft of JEP 193.

This API doesn't use any object to represent a field but uses a String 
as field name, you may think that
1) this mean that the field will be queried each time:
     It doesn't has to. invokedynamic allow to install a dynamic check 
that will test that the string doesn't change
     from one call to another. This check will be removed by the JIT 
because the string never change
     (if the string change, the best is to throw a runtime exception 
like IllegalArgumentException explaining
      that the field name must be a constant).
2) that using a String is not typesafe. Having a typesafe API is hard 
here, because the type of a field
     is not something you can get at compile time, there is no field 
reference syntax in Java (no Foo::i),
     so a String seems to be a good practical choice.

And this API has a true real advantage compared to the VarHandle API, 
this API is inherently more secure.
A VarHandle or any object representing a field will have some special 
security credential because it can access
to a field without having to check at runtime if the field is visible 
from where the call is done (for performance reason).
 From my own experience, it's too easy to make this kind of object too 
visible introduced a security hole without
even doing something hard.
By not reifying the access to a field as an object, the API is more 
secure with the restriction
that a method can only access to the field of the class that contains 
the call to the API.

In term of implementation, the compiler will generate this bytecode for 
the class Foo:

||class  Foo  {

|    int i;

     public void acquire() {
      invokedynamic "compareAndSet" (Foo;String;II)Z
        BSM =||java.lang.invoke.SafeMetaProtocol|||.bootstrap(Lookup;String;MethodType;MethodHandle)
        ARG = MH(||||||Safe.compareAndSet(||Object;String;Object;Object;)
      istore 0||||
      ...
|    }
}|

and from the JLS perspective, the compiler will recognize that the 
method inside Safe
are special because there are annotated by an annotation that has a 
meta-annotation
named BootstrapMethod that specifies the bootstrap method that should be 
used
when emitting the invokedynamic call.

||||

@BootstrapMethod(type=java.lang.invoke.SafeMetaProtocol.class, 
name="bootstrap")
@interface Intrinsic {
   // empty
}

cheers,
Rémi



More information about the valhalla-dev mailing list