FTR: JVM Lang Summit presentation
Paul Sandoz
paul.sandoz at oracle.com
Wed Sep 3 14:49:43 UTC 2014
On Sep 3, 2014, at 4:44 PM, Paul Sandoz <paul.sandoz at oracle.com> wrote:
> I experimented a bit with both of the above (see end of email for code)
Drat, i forgot to add the code in the last email,
Paul.
package java.lang.invoke;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public final class RefFieldVarHandle<R, V> {
private final MethodHandle getVolatile;
private final MethodHandle setVolatile;
private final MethodHandle setRelease;
private final MethodHandle compareAndSet;
private final Class<R> rType;
private final Class<V> vType;
private final long v_offset;
RefFieldVarHandle(MethodHandle getVolatile,
MethodHandle setVolatile,
MethodHandle setRelease,
MethodHandle compareAndSet,
Class<R> rType, Class<V> vType, long v_offset) {
this.getVolatile = getVolatile;
this.setVolatile = setVolatile;
this.setRelease = setRelease;
this.compareAndSet = compareAndSet;
this.rType = rType;
this.vType = vType;
this.v_offset = v_offset;
}
@ForceInline
public boolean compareAndSet_mh(R r, V e, V v) {
r.getClass(); // check for null
try {
return (boolean) compareAndSet.invokeExact(r, e, v);
}
catch (Throwable t) {
if (t instanceof RuntimeException) throw (RuntimeException) t;
if (t instanceof Error) throw (Error) t;
throw new AssertionError(t);
}
}
@ForceInline
public boolean compareAndSet_direct(R r, V e, V v) {
r.getClass(); // check for null
MethodHandleImpl.castReference(rType, r);
MethodHandleImpl.castReference(vType, e);
MethodHandleImpl.castReference(vType, v);
return MethodHandleStatics.UNSAFE.compareAndSwapObject(r, v_offset, e, v);
}
@ForceInline
@SuppressWarnings("unchecked")
public V getVolatile_mh(R r) {
r.getClass(); // check for null
try {
Object v = (Object) getVolatile.invokeExact(r);
return (V) v;
}
catch (Throwable t) {
if (t instanceof RuntimeException) throw (RuntimeException) t;
if (t instanceof Error) throw (Error) t;
throw new AssertionError(t);
}
}
@ForceInline
public V getVolatile_direct(R r) {
r.getClass(); // check for null
Object v = MethodHandleStatics.UNSAFE.getObjectVolatile(r, v_offset);
return MethodHandleImpl.castReference(vType, v);
}
@ForceInline
public void setVolatile_mh(R r, V v) {
r.getClass(); // check for null
try {
setVolatile.invokeExact(r, v);
}
catch (Throwable t) {
if (t instanceof RuntimeException) throw (RuntimeException) t;
if (t instanceof Error) throw (Error) t;
throw new AssertionError(t);
}
}
@ForceInline
public void setVolatile_direct(R r, V v) {
r.getClass(); // check for null
MethodHandleImpl.castReference(rType, r);
MethodHandleImpl.castReference(vType, v);
MethodHandleStatics.UNSAFE.putObjectVolatile(r, v_offset, v);
}
@ForceInline
public void setRelease_mh(R r, V v) {
r.getClass(); // check for null
try {
setRelease.invokeExact(r, v);
}
catch (Throwable t) {
if (t instanceof RuntimeException) throw (RuntimeException) t;
if (t instanceof Error) throw (Error) t;
throw new AssertionError(t);
}
}
@ForceInline
public void setRelease_direct(R r, V v) {
r.getClass(); // check for null
MethodHandleImpl.castReference(rType, r);
MethodHandleImpl.castReference(vType, v);
MethodHandleStatics.UNSAFE.putOrderedObject(r, v_offset, v);
}
public static <R, V> RefFieldVarHandle<R, V> findHandle(Class<R> r, String name, Class<V> v) throws NoSuchFieldException, IllegalAccessException {
MethodHandles.Lookup lookup = MethodHandles.Lookup.IMPL_LOOKUP;
MethodHandle getter = lookup.findGetter(r, name, v);
MethodHandleInfo methodHandleInfo = lookup.revealDirect(getter);
Field field = methodHandleInfo.reflectAs(Field.class, lookup);
long offset = MethodHandleStatics.UNSAFE.objectFieldOffset(field);
MethodHandle getVolatile = MethodHandles.insertArguments(GET_VOLATILE_OBJECT, 1, offset);
getVolatile = getVolatile.asType(MethodType.methodType(v, r));
getVolatile = getVolatile.asType(MethodType.methodType(Object.class, Object.class));
MethodHandle setVolatile = MethodHandles.insertArguments(SET_VOLATILE_OBJECT, 1, offset);
setVolatile = setVolatile.asType(MethodType.methodType(void.class, r, v));
setVolatile = setVolatile.asType(MethodType.methodType(void.class, Object.class, Object.class));
MethodHandle setRelease = MethodHandles.insertArguments(SET_RELEASE_OBJECT, 1, offset);
setRelease = setRelease.asType(MethodType.methodType(void.class, r, v));
setRelease = setRelease.asType(MethodType.methodType(void.class, Object.class, Object.class));
MethodHandle cas = MethodHandles.insertArguments(COMPARE_AND_SWAP_OBJECT, 1, offset);
cas = cas.asType(MethodType.methodType(boolean.class, r, v, v));
cas = cas.asType(MethodType.methodType(boolean.class, Object.class, Object.class, Object.class));
return new RefFieldVarHandle<>(
getVolatile,
setVolatile,
setRelease,
cas,
r, v, offset);
}
static final MethodHandle GET_VOLATILE_OBJECT;
static final MethodHandle SET_VOLATILE_OBJECT;
static final MethodHandle SET_RELEASE_OBJECT;
static final MethodHandle COMPARE_AND_SWAP_OBJECT;
static {
try {
MethodHandle getVolatile = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual(
Unsafe.class,
"getObjectVolatile",
MethodType.methodType(Object.class, Object.class, long.class));
GET_VOLATILE_OBJECT = MethodHandles.insertArguments(getVolatile, 0, MethodHandleStatics.UNSAFE);
MethodHandle setVolatile = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual(
Unsafe.class,
"putObjectVolatile",
MethodType.methodType(void.class, Object.class, long.class, Object.class));
SET_VOLATILE_OBJECT = MethodHandles.insertArguments(setVolatile, 0, MethodHandleStatics.UNSAFE);
MethodHandle setRelease = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual(
Unsafe.class,
"putOrderedObject",
MethodType.methodType(void.class, Object.class, long.class, Object.class));
SET_RELEASE_OBJECT = MethodHandles.insertArguments(setRelease, 0, MethodHandleStatics.UNSAFE);
MethodHandle cas = MethodHandles.Lookup.IMPL_LOOKUP.findVirtual(
Unsafe.class,
"compareAndSwapObject",
MethodType.methodType(boolean.class, Object.class, long.class, Object.class, Object.class));
COMPARE_AND_SWAP_OBJECT = MethodHandles.insertArguments(cas, 0, MethodHandleStatics.UNSAFE);
}
catch (Exception e) {
throw new AssertionError(e);
}
}
}
More information about the valhalla-dev
mailing list