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