On Fri, 23 Oct 2020 20:41:31 GMT, Paul Sandoz <psan...@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

Reply via email to