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