On Fri, 23 Oct 2020 18:06:51 GMT, Jorn Vernee <jver...@openjdk.org> wrote:

>> Hi,
>> 
>> This patch adds an asExact() combinator to VarHandle, that will return a new 
>> VarHandle that performs exact type checks, similar to 
>> MethodHandle::invokeExact, to help developers catch inexact VarHandle usage, 
>> which can lead to performance degradation.
>> 
>> This is implemented using a boolean flag in VarForm. If the flag is set, the 
>> exact type of the invocation is checked against the exact type in the 
>> VarForm. If there is a mismatch, a WrongMethodTypeException is thrown.
>> 
>> Other than that, there is also an asGeneric() combinator added that does the 
>> inverse operation (thanks to Rémi for the suggestion). I've also added The 
>> `@Hidden` annotation to the VarHandleGuards methods, as well as a 
>> type-checking helper method called from the generic invocation lambda form, 
>> so that the stack trace we get points at the location where the VarHandle is 
>> being used.
>> 
>> Thanks,
>> Jorn
>> 
>> GH action link (at time of submission): 
>> https://github.com/JornVernee/jdk/actions/runs/324660237
>
> 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.

-------------

PR: https://git.openjdk.java.net/jdk/pull/843

Reply via email to