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