Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-29 Thread Jorn Vernee
On Tue, 27 Oct 2020 15:01:31 GMT, Jorn Vernee  wrote:

>> I've updated the implementation of accessModeType to work with the ordinal 
>> directly. Note that it was using the AccessType ordinal though, so I also 
>> had to change the parameter type of accessModeTypeUncached, and the 
>> respective implementations, to use AccessType directly (luckily this was 
>> possible, since the current implementations all just used the AccessType).
>
> I think `asInvoker` and `asExactInvoker` make sense if you think of a 
> VarHandle as an invoker of MethodHandles (though this is more of an 
> implementation detail). But, I feel like the name `asInvoker` isn't obvious 
> enough for what it does. i.e. it's not that obvious from the name that this 
> removes the exactness.
> 
> If `asGeneric` is problematic, maybe just `asNonExact` works?

I've uploaded another revision that has the suggested javadoc changes, courtesy 
of Paul. We also decided to rename asExact() and asGeneric() to 
withInvokeExactBehaviour() and withInvokeBehaviour() (with links to the 
relevant javadoc sections).

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-27 Thread Jorn Vernee
On Mon, 26 Oct 2020 18:54:45 GMT, Jorn Vernee  wrote:

>> Paul,
>> an invoker has the MethodHandle (resp. VarHandle) as first argument so it's 
>> not the same semantics.
>
> I've updated the implementation of accessModeType to work with the ordinal 
> directly. Note that it was using the AccessType ordinal though, so I also had 
> to change the parameter type of accessModeTypeUncached, and the respective 
> implementations, to use AccessType directly (luckily this was possible, since 
> the current implementations all just used the AccessType).

I think `asInvoker` and `asExactInvoker` make sense if you think of a VarHandle 
as an invoker of MethodHandles (though this is more of an implementation 
detail). But, I feel like the name `asInvoker` isn't obvious enough for what it 
does. i.e. it's not that obvious from the name that this removes the exactness.

If `asGeneric` is problematic, maybe just `asNonExact` works?

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-26 Thread Jorn Vernee
On Mon, 26 Oct 2020 17:13:05 GMT, Rémi Forax 
 wrote:

>> 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:
>> 
>>  * 
>>  * 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:
>>  *  {@code
>>  * VarHandle vh = ..
>>  * R r = (R) vh.{access-mode}(p1, p2, ..., pN);
>>  * }
>>  * behaves as if:
>>  *  {@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)
>>  * }
>>  * (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.
>
> Paul,
> an invoker has the MethodHandle (resp. VarHandle) as first argument so it's 
> not the same semantics.

I've updated the implementation of accessModeType to work with the ordinal 
directly. Note that it was using the AccessType ordinal though, so I also had 
to change the parameter type of accessModeTypeUncached, and the respective 
implementations, to use AccessType directly (luckily this was possible, since 
the current implementations all just used the AccessType).

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-26 Thread Rémi Forax
On Mon, 26 Oct 2020 16:34:10 GMT, Paul Sandoz  wrote:

>> 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:
> 
>  * 
>  * 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:
>  *  {@code
>  * VarHandle vh = ..
>  * R r = (R) vh.{access-mode}(p1, p2, ..., pN);
>  * }
>  * behaves as if:
>  *  {@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)
>  * }
>  * (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.

Paul,
an invoker has the MethodHandle (resp. VarHandle) as first argument so it's not 
the same semantics.

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-26 Thread Paul Sandoz
On Mon, 26 Oct 2020 16:13:59 GMT, Paul Sandoz  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_exactInvocationavgt   
>> 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:

 * 
 * 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:
 *  {@code
 * VarHandle vh = ..
 * R r = (R) vh.{access-mode}(p1, p2, ..., pN);
 * }
 * behaves as if:
 *  {@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)
 * }
 * (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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-26 Thread Paul Sandoz
On Mon, 26 Oct 2020 13:37:58 GMT, Jorn Vernee  wrote:

>> @PaulSandoz I've implemented your suggestion, by moving the `exact` flag to 
>> VarHandle itself. FWIW, the VH::accessModeType method took an AccessMode 
>> value as an argument, and the AccessDescriptor only stored the ordinal, so I 
>> added an `@Stable` array of values to AccessMode to map from ordinal to enum 
>> value. But, maybe it makes more sense to just store the AccessMode in the 
>> AccessDescriptor directly? (instead of the ordinal). Not sure what the 
>> original motivation was for only storing the ordinal.
>> 
>> I've also sharpened the tests to check the exception message. Do you think 
>> the testing is sufficient? (Note that I did not add tests to the template 
>> files since only a select set of argument type conversions causes the WMTE 
>> we're looking for. So, that's why I created a new test file).
>> 
>> FWIW, there seems to have been a bug in the implementation of 
>> IndirectVarHandle::accessModeTypeUncached, where it was using the 
>> VarHandle's type as the receiver argument (unlike all the other impls). I've 
>> fixed this by passing `null` instead, and also removed a workaround for this 
>> problem in VarHandles::maybeAdapt.
>
> 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_exactInvocationavgt   
> 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 type, 
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.

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-26 Thread Jorn Vernee
On Fri, 23 Oct 2020 23:58:29 GMT, Jorn Vernee  wrote:

>> @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).
>
> @PaulSandoz I've implemented your suggestion, by moving the `exact` flag to 
> VarHandle itself. FWIW, the VH::accessModeType method took an AccessMode 
> value as an argument, and the AccessDescriptor only stored the ordinal, so I 
> added an `@Stable` array of values to AccessMode to map from ordinal to enum 
> value. But, maybe it makes more sense to just store the AccessMode in the 
> AccessDescriptor directly? (instead of the ordinal). Not sure what the 
> original motivation was for only storing the ordinal.
> 
> I've also sharpened the tests to check the exception message. Do you think 
> the testing is sufficient? (Note that I did not add tests to the template 
> files since only a select set of argument type conversions causes the WMTE 
> we're looking for. So, that's why I created a new test file).
> 
> FWIW, there seems to have been a bug in the implementation of 
> IndirectVarHandle::accessModeTypeUncached, where it was using the VarHandle's 
> type as the receiver argument (unlike all the other impls). I've fixed this 
> by passing `null` instead, and also removed a workaround for this problem in 
> VarHandles::maybeAdapt.

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).

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-23 Thread Jorn Vernee
On Fri, 23 Oct 2020 21:38:16 GMT, Jorn Vernee  wrote:

>> 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).

@PaulSandoz I've implemented your suggestion. FWIW, the VH::accessModeType 
method took and AccessMode value as an argument, and the AccessDescriptor only 
stored the ordinal, so I added an `@Stable` array of values to AccessMode to 
map from ordinal to enum value. But, maybe it makes more sense to just store 
the AccessMode in the AccessDescriptor directly? (instead of the ordinal). Not 
sure what the original motivation was for only storing the ordinal.

I've also sharpened the tests to check the exception message. Do you think the 
testing is sufficient? (Note that I did not add tests to the template files 
since only a select set of argument type conversions causes the WMTE we're 
looking for. So, that's why I created a new test file).

FWIW, there seems to have been a bug in the implementation of 
IndirectVarHandle::accessModeTypeUncached, where it was using the VarHandle's 
type as the receiver argument (unlike all the other impls). I've fixed this by 
passing `null` instead, and also removed a workaround for this problem in 
VarHandles::maybeAdapt.

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-23 Thread Jorn Vernee
On Fri, 23 Oct 2020 20:41:31 GMT, Paul Sandoz  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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-23 Thread Paul Sandoz
On Fri, 23 Oct 2020 18:06:51 GMT, Jorn Vernee  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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-23 Thread Jorn Vernee
On Fri, 23 Oct 2020 18:02:11 GMT, Rémi Forax 
 wrote:

>> Jorn Vernee has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   Make internalName helper method static
>
> src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java
>  line 450:
> 
>> 448: }
>> 449: 
>> 450: private String internalName(Class cls) {
> 
> should be static, no ?

Yes, thanks.

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-23 Thread Rémi Forax
On Fri, 23 Oct 2020 18:04:11 GMT, Jorn Vernee  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.
>> 
>> Thanks,
>> Jorn
>
> Jorn Vernee has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Make internalName helper method static

src/java.base/share/classes/java/lang/invoke/MemoryAccessVarHandleGenerator.java
 line 450:

> 448: }
> 449: 
> 450: private String internalName(Class cls) {

should be static, no ?

-

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


Re: RFR: 8254354: Add an asExact() VarHandle combinator [v2]

2020-10-23 Thread Jorn Vernee
> 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.
> 
> Thanks,
> Jorn

Jorn Vernee has updated the pull request incrementally with one additional 
commit since the last revision:

  Make internalName helper method static

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/843/files
  - new: https://git.openjdk.java.net/jdk/pull/843/files/65c5d145..dc1f9ecf

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk&pr=843&range=01
 - incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=843&range=00-01

  Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod
  Patch: https://git.openjdk.java.net/jdk/pull/843.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/843/head:pull/843

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