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