On Mon, 26 Oct 2020 16:13:59 GMT, Paul Sandoz <psan...@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

Reply via email to