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