RFR: 8254354: Add an asExact() VarHandle combinator [v2]

Paul Sandoz psandoz at openjdk.java.net
Mon Oct 26 16:37:18 UTC 2020


On Mon, 26 Oct 2020 16:13:59 GMT, Paul Sandoz <psandoz at openjdk.org> wrote:

>> I've updated the javadoc, and added two benchmarks that show the existing discrepancy between an exact and a generic use of a VarHandle, as well as showing that an exact VarHandle is as fast as a generic VarHandle for an exact invocation. (1 benchmark for normal Java field access, and 1 benchmark for the foreign memory-access API).
>> 
>> Benchmark                                                             Mode  Cnt   Score   Error  Units
>> o.o.b.java.lang.invoke.VarHandleExact.exact_exactInvocation           avgt   30   0.729 □ 0.010  ns/op
>> o.o.b.java.lang.invoke.VarHandleExact.generic_exactInvocation         avgt   30   0.735 □ 0.019  ns/op
>> o.o.b.java.lang.invoke.VarHandleExact.generic_genericInvocation       avgt   30  14.696 □ 0.498  ns/op
>> o.o.b.jdk.incubator.foreign.VarHandleExact.exact_exactInvocation      avgt   30   2.274 □ 0.012  ns/op
>> o.o.b.jdk.incubator.foreign.VarHandleExact.generic_exactInvocation    avgt   30   2.278 □ 0.015  ns/op
>> o.o.b.jdk.incubator.foreign.VarHandleExact.generic_genericInvocation  avgt   30  24.759 □ 0.367  ns/op
>
> The direct use of the enum ordinal is because HotSpot accessing it from the enum value is (or was) not optimal in C2.
>  
> You can avoid the addition of the stable array by doing the following:
> 
>     public final MethodType accessModeType(AccessMode accessMode) {
>         return accessModeType(accessMode.at.ordinal());
>     }
> 
>     @ForceInline
>     final MethodType accessModeType(int accessModeOrdinal) {
>         TypesAndInvokers tis = getTypesAndInvokers();
>         MethodType mt = tis.methodType_table[accessModeOrdinal];
>         if (mt == null) {
>             mt = tis.methodType_table[accessModeOrdinal] =
>                     accessModeTypeUncached(accessModeOrdinal);
>         }
>         return mt;
>     }
> 
>     final MethodType accessModeTypeUncached(int accessModeOrdinal) {
>         return accessModeTypeUncached(AccessMode.values()[accessModeOrdinal]);
>     }
> It's a little odd going back and forth between the ordinal and the enum value, but it's all on the slow uncached path, and it avoids some duplication of code.
> 
> I'll take a closer looks at the other areas and respond in another comment.

We can clarify the new methods and tie them closer to method handle semantics. I suggest the names `asExactInvoker` and `asInvoker`, referencing `MethodHandles.exactInvoker` and `MethodHandles.invoker` respectively. (The term "generic" is really reserved for erased method types, and otherwise used internally as the generic invoker.)

The `VarHandle` documentation already specifies that:

 * <p>
 * Invocation of an access mode method behaves as if an invocation of
 * {@link MethodHandle#invoke}, where the receiving method handle accepts the
 * VarHandle instance as the leading argument.  More specifically, the
 * following, where {@code {access-mode}} corresponds to the access mode method
 * name:
 * <pre> {@code
 * VarHandle vh = ..
 * R r = (R) vh.{access-mode}(p1, p2, ..., pN);
 * }</pre>
 * behaves as if:
 * <pre> {@code
 * VarHandle vh = ..
 * VarHandle.AccessMode am = VarHandle.AccessMode.valueFromMethodName("{access-mode}");
 * MethodHandle mh = MethodHandles.varHandleExactInvoker(
 *                       am,
 *                       vh.accessModeType(am));
 *
 * R r = (R) mh.invoke(vh, p1, p2, ..., pN)
 * }</pre>
 * (modulo access mode methods do not declare throwing of {@code Throwable}).
...

 We will need to adjust this section, i can help, but first let us reach agreement on this approach.

-------------

PR: https://git.openjdk.java.net/jdk/pull/843


More information about the core-libs-dev mailing list