RFR: 8254354: Add an asExact() VarHandle combinator [v2]
Jorn Vernee
jvernee at openjdk.java.net
Fri Oct 23 21:40:34 UTC 2020
On Fri, 23 Oct 2020 20:41:31 GMT, Paul Sandoz <psandoz at openjdk.org> wrote:
>> Jorn Vernee has updated the pull request incrementally with one additional commit since the last revision:
>>
>> Make internalName helper method static
>
> This approach does not work for reference types, since they are erased to `Object`, and then exact checking will be performed on the erased reference types.
>
> For example try this:
>
> import java.lang.invoke.MethodHandles;
> import java.lang.invoke.VarHandle;
>
> public class Test {
> int x;
>
> public static void main(String[] args) throws Throwable {
> VarHandle x = MethodHandles.lookup().findVarHandle(Test.class, "x", int.class);
> VarHandle ex = x.asExact();
> Test t = new Test();
> ex.set(t, 1);
> }
> }
>
> Which results in:
>
> Exception in thread "main" java.lang.invoke.WrongMethodTypeException: expected (Object,int)void but found (Test,int)void
> at Test.main(Test.java:11)
>
> Exact type checking requires that match be performed on the VH access mode method type and the exact symbolic method type, something like:
>
> final static Object guard_L_L(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
> if (handle.vform.exact && handle.accessModeType(ad.type) != ad.symbolicMethodTypeExact) {
> throw new WrongMethodTypeException("expected " + handle.vform.methodType_table_exact[ad.type] + " but found "
> + ad.symbolicMethodTypeExact);
> }
>
> Then it's precisely the same as `MH.invokeExact`, rather than `MH.invoke`.
>
> A `VarForm` is a resource shared across many instances of the same _kind_ of `VarHandle`, so cannot be used for exact matching, except in specific scenarios e.g. access on a primitive array.
@PaulSandoz Thanks. I initially tested this with memory access VarHandles, which don't erase the receiver type. e.g.
MemoryLayout layout = MemoryLayout.ofSequence(10, JAVA_INT);
VarHandle vh = layout.varHandle(int.class, MemoryLayout.PathElement.sequenceElement());
vh = vh.asExact();
try (MemorySegment segment = MemorySegment.allocateNative(layout)) {
for (int i = 0; i <10; i++) {
vh.set(segment.baseAddress(), i, i);
}
}
Will result in:
Exception in thread "main" java.lang.invoke.WrongMethodTypeException: expected (MemoryAddress,long,int)void but found (MemoryAddress,int,int)void
at java.base/java.lang.invoke.VarHandleGuards.guard_LII_V(VarHandleGuards.java:915)
at main.Main.main(Main.java:18)
Which led me to believe the approach would work for other reference types. But, I suppose the MethodTypes fed to memaccess VarForms are non-erased as an exception rather than a rule.
I'll update the patch and sharpen the tests to check that the actual expected type is correct (per the exception message).
-------------
PR: https://git.openjdk.java.net/jdk/pull/843
More information about the core-libs-dev
mailing list