Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-06-01 Thread Chen Liang
On Sun, 7 May 2023 13:34:54 GMT, Chen Liang  wrote:

>> As John Rose has pointed out in this issue, the current j.l.r.Proxy based 
>> implementation of MethodHandleProxies.asInterface has a few issues:
>> 1. Exposes too much information via Proxy supertype (and WrapperInstance 
>> interface)
>> 2. Does not allow future expansion to support SAM[^1] abstract classes
>> 3. Slow (in fact, very slow)
>> 
>> This patch addresses all 3 problems:
>> 1. It updates the WrapperInstance methods to take an `Empty` to avoid method 
>> clashes
>> 2. This patch obtains already generated classes from a ClassValue by the 
>> requested interface type; the ClassValue can later be updated to compute 
>> implementation generation for abstract classes as well.
>> 3. This patch's faster than old implementation in general.
>> 
>> 
>> Benchmark  Mode  Cnt 
>>  Score  Error  Units
>> MethodHandleProxiesAsIFInstance.baselineAllocCompute   avgt   15 
>>  1.483 ±0.025  ns/op
>> MethodHandleProxiesAsIFInstance.baselineComputeavgt   15 
>>  0.264 ±0.006  ns/op
>> MethodHandleProxiesAsIFInstance.testCall   avgt   15 
>>  1.773 ±0.040  ns/op
>> MethodHandleProxiesAsIFInstance.testCreate avgt   15 
>> 16.754 ±0.411  ns/op
>> MethodHandleProxiesAsIFInstance.testCreateCall avgt   15 
>> 19.609 ±1.598  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callDoable avgt   15 
>>  0.424 ±0.024  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callHandle avgt   15 
>>  1.936 ±0.008  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callInterfaceInstance  avgt   15 
>>  1.766 ±0.014  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callLambda avgt   15 
>>  0.414 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantDoable avgt   15 
>>  0.271 ±0.006  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantHandle avgt   15 
>>  0.263 ±0.004  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantInterfaceInstance  avgt   15 
>>  0.266 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantLambda avgt   15 
>>  0.262 ±0.003  ns/op
>> MethodHandleProxiesAsIFInstanceCall.direct avgt   15 
>>  0.264 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCreate.createCallInterfaceInstance  avgt   15 
>> 18.000 ±0.181  ns/op
>> MethodHandleProxiesAsIFInstanceCreat...
>
> Chen Liang has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Remove assertion, no longer true with teleport definition in MHP

About the security manager: the proposal to change SecurityManager to permit 
exporting the internal API packages would change the specification of 
`SecurityManger::checkPackageAccess`. Should I touch that in this patch and 
potentially require CSR review about SecurityManager changes, or should I go 
back to the original Proxy-like checks?

-

PR Comment: https://git.openjdk.org/jdk/pull/13197#issuecomment-1572243080


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-31 Thread Johannes Kuhn
On Wed, 31 May 2023 00:49:22 GMT, Mandy Chung  wrote:

>>> Apparently, calling utility methods from sun.invoke, like the 
>>> ensureOriginalLookup in this patch, also triggers this check. 
>> 
>> It should not trigger `checkPackageAccess` if it does not implement the 
>> interface AFAICT.
>> 
>> It would trigger module-access check.  `java.base` can export `sun.invoke` 
>> to the dynamic module (it may be worth considering putting the internal 
>> interface in a specific package for the dynamic module' use - `sun.invoke` 
>> is ok since it currently has one interface but hard to catch when someone 
>> adds a new class/interface in `sun.invoke` unintentionally and leak out 
>> sensitive API.
>
>> Then we still need to obtain the implemented interface and original method 
>> handle information every time they are queried. Having these information (or 
>> the method handle providing access) computed early is more convenient.
> 
> I was thinking the wrapper instance class still implements some private 
> methods to get the implemented interface and original method handle which can 
> be accessed only `java.base` via deep reflection.

> It should not trigger `checkPackageAccess` if it does not implement the 
> interface AFAICT.

`checkPackageAccess` is also called by the application class loader:
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java#L174-L189

It should make it impossible to reference for example `sun.misc.Unsafe`.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1211652282


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-30 Thread Mandy Chung
On Wed, 31 May 2023 00:27:24 GMT, Chen Liang  wrote:

> Apparently, calling utility methods from sun.invoke, like the 
> ensureOriginalLookup in this patch, also triggers this check. 

It should not trigger `checkPackageAccess` if it does not implement the 
interface AFAICT.

It would trigger module-access check.  `java.base` can export `sun.invoke` to 
the dynamic module (it may be worth considering putting the internal interface 
in a specific package for the dynamic module' use - `sun.invoke` is ok since it 
currently has one interface but hard to catch when someone adds a new 
class/interface in `sun.invoke` unintentionally and leak out sensitive API.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1210971821


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-30 Thread Mandy Chung
On Wed, 31 May 2023 00:48:18 GMT, Mandy Chung  wrote:

>>> Is it more straight-forward to keep a `ClassValue` and each 
>>> wrapper instance class has an entry of `TRUE` value; otherwise, `FALSE`?
>> 
>> Then we still need to obtain the implemented interface and original method 
>> handle information every time they are queried. Having these information (or 
>> the method handle providing access) computed early is more convenient.
>> 
>>> If we can avoid implementing sun.invoke.WrapperInstance, this package 
>>> access check issue would go away. Do you think you can look into it?
>> 
>> Apparently, calling utility methods from `sun.invoke`, like the 
>> `ensureOriginalLookup` in this patch, also triggers this check. However, I 
>> still think removing the `WrapperInstance` supertype is better, as this 
>> makes the code cleaner in reflection.
>
>> Apparently, calling utility methods from sun.invoke, like the 
>> ensureOriginalLookup in this patch, also triggers this check. 
> 
> It should not trigger `checkPackageAccess` if it does not implement the 
> interface AFAICT.
> 
> It would trigger module-access check.  `java.base` can export `sun.invoke` to 
> the dynamic module (it may be worth considering putting the internal 
> interface in a specific package for the dynamic module' use - `sun.invoke` is 
> ok since it currently has one interface but hard to catch when someone adds a 
> new class/interface in `sun.invoke` unintentionally and leak out sensitive 
> API.

> Then we still need to obtain the implemented interface and original method 
> handle information every time they are queried. Having these information (or 
> the method handle providing access) computed early is more convenient.

I was thinking the wrapper instance class still implements some private methods 
to get the implemented interface and original method handle which can be 
accessed only `java.base` via deep reflection.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1210972245


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-30 Thread Chen Liang
On Wed, 31 May 2023 00:01:56 GMT, Mandy Chung  wrote:

> Is it more straight-forward to keep a `ClassValue` and each wrapper 
> instance class has an entry of `TRUE` value; otherwise, `FALSE`?

Then we still need to obtain the implemented interface and original method 
handle information every time they are queried. Having these information (or 
the method handle providing access) computed early is more convenient.

> If we can avoid implementing sun.invoke.WrapperInstance, this package access 
> check issue would go away. Do you think you can look into it?

Apparently, calling utility methods from `sun.invoke`, like the 
`ensureOriginalLookup` in this patch, also triggers this check. However, I 
still think removing the `WrapperInstance` supertype is better, as this makes 
the code cleaner in reflection.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1210963364


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-30 Thread Mandy Chung
On Fri, 26 May 2023 22:18:17 GMT, Chen Liang  wrote:

>> If we can avoid implementing `sun.invoke.WrapperInstance`, this package 
>> access check issue would go away.  Do you think you can look into it?
>
> I think we can probably insert a static final field in a wrapper instance 
> class to point to the implemented class and verify with the 
> `PROXY_CLASS_INFOS` ClassValue, much like VarForm field in VarHandle 
> implementations. This should have less reflective impact than the 
> annotation-based approach, and can be cached in a ClassValue as well. Should 
> we cache it though?

Is it more straight-forward to keep a `ClassValue` and each wrapper 
instance class has an entry of `TRUE` value; otherwise, `FALSE`?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1210952258


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Chen Liang
On Fri, 26 May 2023 22:05:06 GMT, Mandy Chung  wrote:

>>> because a conditionally-exported package is considered a 
>>> non-(unconditionally-)exported package.
>> 
>> OK.  I need to look into the right solution for this.   The Proxy 
>> implementation uses null protection domain to define the proxy class whereas 
>> this patch uses the protection domain as the interface to define the MHProxy 
>> class.  That's why this issue only occurs in this new implementation.
>
> If we can avoid implementing `sun.invoke.WrapperInstance`, this package 
> access check issue would go away.  Do you think you can look into it?

I think we can probably insert a static final field in a wrapper instance class 
to point to the implemented class and verify with the `PROXY_CLASS_INFOS` 
ClassValue, much like VarForm field in VarHandle implementations. This should 
have less reflective impact than the annotation-based approach, and can be 
cached in a ClassValue as well. Should we cache it though?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207426728


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Mandy Chung
On Fri, 26 May 2023 22:03:40 GMT, Mandy Chung  wrote:

>> If we keep a cache of all MHProxy classes, I think this would not need 
>> `sun.invoke.WrapperInstance`.   OTOH, `sun.invoke` does not have any other 
>> class except `WrapperInstance` and the `ensureOriginalLookup` method would 
>> need to be in an internal class.   So no problem of implementing 
>> `sun.invoke.WrapperInstance`.
>
>> because a conditionally-exported package is considered a 
>> non-(unconditionally-)exported package.
> 
> OK.  I need to look into the right solution for this.   The Proxy 
> implementation uses null protection domain to define the proxy class whereas 
> this patch uses the protection domain as the interface to define the MHProxy 
> class.  That's why this issue only occurs in this new implementation.

If we can avoid implementing `sun.invoke.WrapperInstance`, this package access 
check issue would go away.  Do you think you can look into it?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207416972


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Mandy Chung
On Fri, 26 May 2023 21:29:14 GMT, Chen Liang  wrote:

>>> This approach also requires the Class loading checks since the interface is 
>>> not unconditionally exported and fails security manager.
>> 
>> Are you referring to `ClassLoader::checkPackageAccess` change?   As MHProxy 
>> implements `sun.invoke.WrapperInstance`, it needs to export 
>> `java.base/sun.invoke` to the dynamic module.The change to 
>> `ClassLoader::checkPackageAccess` doesn't make sense for this.
>
> Yes. Unfortunately, it fails at 
> https://github.com/openjdk/jdk/blob/bd21e68e679c41c98f39dd2fbd38270ae7d55ed9/src/java.base/share/classes/java/lang/SecurityManager.java#L1317
>  because a conditionally-exported package is considered a 
> non-(unconditionally-)exported package.

If we keep a cache of all MHProxy classes, I think this would not need 
`sun.invoke.WrapperInstance`.   OTOH, `sun.invoke` does not have any other 
class except `WrapperInstance` and the `ensureOriginalLookup` method would need 
to be in an internal class.   So no problem of implementing 
`sun.invoke.WrapperInstance`.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207387430


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Mandy Chung
On Fri, 26 May 2023 21:31:40 GMT, Mandy Chung  wrote:

>> Yes. Unfortunately, it fails at 
>> https://github.com/openjdk/jdk/blob/bd21e68e679c41c98f39dd2fbd38270ae7d55ed9/src/java.base/share/classes/java/lang/SecurityManager.java#L1317
>>  because a conditionally-exported package is considered a 
>> non-(unconditionally-)exported package.
>
> If we keep a cache of all MHProxy classes, I think this would not need 
> `sun.invoke.WrapperInstance`.   OTOH, `sun.invoke` does not have any other 
> class except `WrapperInstance` and the `ensureOriginalLookup` method would 
> need to be in an internal class.   So no problem of implementing 
> `sun.invoke.WrapperInstance`.

> because a conditionally-exported package is considered a 
> non-(unconditionally-)exported package.

OK.  I need to look into the right solution for this.   The Proxy 
implementation uses null protection domain to define the proxy class whereas 
this patch uses the protection domain as the interface to define the MHProxy 
class.  That's why this issue only occurs in this new implementation.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207415941


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Mandy Chung
On Fri, 26 May 2023 21:06:36 GMT, Chen Liang  wrote:

>> src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 
>> 209:
>> 
>>> 207: if (intfc.isHidden())
>>> 208: throw newIllegalArgumentException("a hidden interface", 
>>> intfc.getName());
>>> 209: if (!VM.isModuleSystemInited())
>> 
>> I don't expect this is needed.  I assume you are thinking for LMF to use 
>> this API?
>
> Proxy-based impl had this check, so I'd assume MHP might want to defend 
> against the same kind of improper usage.

Proxy is used by annotation implementation.   I suspect that's why that check 
was there.

For `MHP::asInterfaceInstance`, I would drop the `isModuleSystemInitied` check 
until the API is being used during early startup.   I don't expect it be called 
before module system is initialized.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207391651


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Chen Liang
On Fri, 26 May 2023 21:23:32 GMT, Mandy Chung  wrote:

>> John Rose argues against using class data for Leyden. Since class data is 
>> the only known way to defend against user-manufactured annotations, I 
>> switched back to an extra wrapper interface. This approach also requires the 
>> Class loading checks since the interface is not unconditionally exported and 
>> fails security manager.
>
>> This approach also requires the Class loading checks since the interface is 
>> not unconditionally exported and fails security manager.
> 
> Are you referring to `ClassLoader::checkPackageAccess` change?   As MHProxy 
> implements `sun.invoke.WrapperInstance`, it needs to export 
> `java.base/sun.invoke` to the dynamic module.The change to 
> `ClassLoader::checkPackageAccess` doesn't make sense for this.

Yes. Unfortunately, it fails at 
https://github.com/openjdk/jdk/blob/bd21e68e679c41c98f39dd2fbd38270ae7d55ed9/src/java.base/share/classes/java/lang/SecurityManager.java#L1317
 because a conditionally-exported package is considered a 
non-(unconditionally-)exported package.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207384208


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Mandy Chung
On Fri, 26 May 2023 21:05:39 GMT, Chen Liang  wrote:

> This approach also requires the Class loading checks since the interface is 
> not unconditionally exported and fails security manager.

Are you referring to `ClassLoader::checkPackageAccess` change?   As MHProxy 
implements `sun.invoke.WrapperInstance`, it needs to export 
`java.base/sun.invoke` to the dynamic module.The change to 
`ClassLoader::checkPackageAccess` doesn't make sense for this.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207376506


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Chen Liang
On Fri, 26 May 2023 18:39:53 GMT, Mandy Chung  wrote:

>> Chen Liang has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   Remove assertion, no longer true with teleport definition in MHP
>
> src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 
> 209:
> 
>> 207: if (intfc.isHidden())
>> 208: throw newIllegalArgumentException("a hidden interface", 
>> intfc.getName());
>> 209: if (!VM.isModuleSystemInited())
> 
> I don't expect this is needed.  I assume you are thinking for LMF to use this 
> API?

Proxy-based impl had this check, so I'd assume MHP might want to defend against 
the same kind of improper usage.

> src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 
> 433:
> 
>> 431: 
>> 432: private static WrapperInstance asWrapperInstance(Object x) {
>> 433: if (x instanceof WrapperInstance wrapperInstance)
> 
> In the previous version, `WrapperInstance` was not needed.  Instead it checks 
> if the class is a  MHProxy class.   Did you run into any issue that you 
> resurrect `WrapperInstance`?Is it just because of accessing 
> `ensureOriginalLookup`?

John Rose argues against using class data for Leyden. Since class data is the 
only known way to defend against user-manufactured annotations, I switched back 
to an extra wrapper interface. This approach also requires the Class loading 
checks since the interface is not unconditionally exported and fails security 
manager.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207350363
PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1207349212


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-26 Thread Mandy Chung
On Sun, 7 May 2023 13:34:54 GMT, Chen Liang  wrote:

>> As John Rose has pointed out in this issue, the current j.l.r.Proxy based 
>> implementation of MethodHandleProxies.asInterface has a few issues:
>> 1. Exposes too much information via Proxy supertype (and WrapperInstance 
>> interface)
>> 2. Does not allow future expansion to support SAM[^1] abstract classes
>> 3. Slow (in fact, very slow)
>> 
>> This patch addresses all 3 problems:
>> 1. It updates the WrapperInstance methods to take an `Empty` to avoid method 
>> clashes
>> 2. This patch obtains already generated classes from a ClassValue by the 
>> requested interface type; the ClassValue can later be updated to compute 
>> implementation generation for abstract classes as well.
>> 3. This patch's faster than old implementation in general.
>> 
>> 
>> Benchmark  Mode  Cnt 
>>  Score  Error  Units
>> MethodHandleProxiesAsIFInstance.baselineAllocCompute   avgt   15 
>>  1.483 ±0.025  ns/op
>> MethodHandleProxiesAsIFInstance.baselineComputeavgt   15 
>>  0.264 ±0.006  ns/op
>> MethodHandleProxiesAsIFInstance.testCall   avgt   15 
>>  1.773 ±0.040  ns/op
>> MethodHandleProxiesAsIFInstance.testCreate avgt   15 
>> 16.754 ±0.411  ns/op
>> MethodHandleProxiesAsIFInstance.testCreateCall avgt   15 
>> 19.609 ±1.598  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callDoable avgt   15 
>>  0.424 ±0.024  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callHandle avgt   15 
>>  1.936 ±0.008  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callInterfaceInstance  avgt   15 
>>  1.766 ±0.014  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callLambda avgt   15 
>>  0.414 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantDoable avgt   15 
>>  0.271 ±0.006  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantHandle avgt   15 
>>  0.263 ±0.004  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantInterfaceInstance  avgt   15 
>>  0.266 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantLambda avgt   15 
>>  0.262 ±0.003  ns/op
>> MethodHandleProxiesAsIFInstanceCall.direct avgt   15 
>>  0.264 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCreate.createCallInterfaceInstance  avgt   15 
>> 18.000 ±0.181  ns/op
>> MethodHandleProxiesAsIFInstanceCreat...
>
> Chen Liang has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Remove assertion, no longer true with teleport definition in MHP

src/hotspot/share/prims/jvm.cpp line 1019:

> 1017: }
> 1018:   }
> 1019:   assert(Reflection::is_same_class_package(lookup_k, ik),

I use the Lookup of the proxy interface to define a hidden class in a dynamic 
module as the dynamic module has no class yet and it's defined to the class 
loader of the proxy interface. 

We should keep the same package check if the defined class is a normal class or 
a hidden nestmate class.   It only allows the lookup class be in a different 
package for defining a hidden non-nestmate class.   This is only internal 
capability.`Lookup::defineHiddenClass` API will throw IAE if the given 
bytes denotes a class in a different package than the lookup class.


+  if ((!is_hidden || is_nestmate) && 
!Reflection::is_same_class_package(lookup_k, ik)) { 
+// non-hidden class or nestmate class must be in the same package as the 
Lookup class
+THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class 
and defined class are in different packages");
+  }
+

src/java.base/share/classes/java/lang/ClassLoader.java line 685:

> 683: final SecurityManager sm = System.getSecurityManager();
> 684: if (sm != null) {
> 685: if (ReflectUtil.isNonPublicProxyClass(cls) || 
> ReflectUtil.isMethodHandleProxiesClass(cls)) {

Why do you need this?   `Proxy` allows non-public interface whereas 
`MethodHandleProxies` only allows public interface.

src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 209:

> 207: if (intfc.isHidden())
> 208: throw newIllegalArgumentException("a hidden interface", 
> intfc.getName());
> 209: if (!VM.isModuleSystemInited())

I don't expect this is needed.  I assume you are thinking for LMF to use this 
API?

src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 245:

> 243: private record LocalMethodInfo(MethodTypeDesc desc, List 
> thrown, String fieldName) {}
> 244: 
> 245: private record ProxyClassInfo(MethodHandle constructor, Lookup 
> originalLookup) {}

`ProxyClassInfo` for interface `I` will be stored in the class value of `I`. 

Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-08 Thread Rémi Forax
On Mon, 8 May 2023 10:46:34 GMT, Maurizio Cimadamore  
wrote:

>> src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 
>> 342:
>> 
>>> 340: 
>>> 341: // individual handle fields
>>> 342: clb.withField(ORIGINAL_TARGET_NAME, CD_MethodHandle, 
>>> ACC_PRIVATE | ACC_FINAL);
>> 
>> Would a @Stable field help here? E.g if the returned functional interface 
>> instance is stored in a `static final` field, it should enable better 
>> performance?
>
> (actually, not sure - as the class is saved in a class value cache, so 
> probably adding stable won't make any difference).

The class is loaded as a hidden class, so all final fields are truly final 
(unlike classes but like records), so @Stable is not needed.

The class value cache only change performance if the cache was used in a hot 
path. And currently a class value cache is not considered as a cache by the 
JIT, i.e. the JIT does not know that if the key is a constant, the value is a 
constant.

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1187495168


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-08 Thread Maurizio Cimadamore
On Mon, 8 May 2023 09:32:31 GMT, Maurizio Cimadamore  
wrote:

>> Chen Liang has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   Remove assertion, no longer true with teleport definition in MHP
>
> src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 
> 342:
> 
>> 340: 
>> 341: // individual handle fields
>> 342: clb.withField(ORIGINAL_TARGET_NAME, CD_MethodHandle, 
>> ACC_PRIVATE | ACC_FINAL);
> 
> Would a @Stable field help here? E.g if the returned functional interface 
> instance is stored in a `static final` field, it should enable better 
> performance?

(actually, not sure - as the class is saved in a class value cache, so probably 
adding stable won't make any difference).

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1187300990


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-08 Thread Maurizio Cimadamore
On Sun, 7 May 2023 13:34:54 GMT, Chen Liang  wrote:

>> As John Rose has pointed out in this issue, the current j.l.r.Proxy based 
>> implementation of MethodHandleProxies.asInterface has a few issues:
>> 1. Exposes too much information via Proxy supertype (and WrapperInstance 
>> interface)
>> 2. Does not allow future expansion to support SAM[^1] abstract classes
>> 3. Slow (in fact, very slow)
>> 
>> This patch addresses all 3 problems:
>> 1. It updates the WrapperInstance methods to take an `Empty` to avoid method 
>> clashes
>> 2. This patch obtains already generated classes from a ClassValue by the 
>> requested interface type; the ClassValue can later be updated to compute 
>> implementation generation for abstract classes as well.
>> 3. This patch's faster than old implementation in general.
>> 
>> 
>> Benchmark  Mode  Cnt 
>>  Score  Error  Units
>> MethodHandleProxiesAsIFInstance.baselineAllocCompute   avgt   15 
>>  1.483 ±0.025  ns/op
>> MethodHandleProxiesAsIFInstance.baselineComputeavgt   15 
>>  0.264 ±0.006  ns/op
>> MethodHandleProxiesAsIFInstance.testCall   avgt   15 
>>  1.773 ±0.040  ns/op
>> MethodHandleProxiesAsIFInstance.testCreate avgt   15 
>> 16.754 ±0.411  ns/op
>> MethodHandleProxiesAsIFInstance.testCreateCall avgt   15 
>> 19.609 ±1.598  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callDoable avgt   15 
>>  0.424 ±0.024  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callHandle avgt   15 
>>  1.936 ±0.008  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callInterfaceInstance  avgt   15 
>>  1.766 ±0.014  ns/op
>> MethodHandleProxiesAsIFInstanceCall.callLambda avgt   15 
>>  0.414 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantDoable avgt   15 
>>  0.271 ±0.006  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantHandle avgt   15 
>>  0.263 ±0.004  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantInterfaceInstance  avgt   15 
>>  0.266 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCall.constantLambda avgt   15 
>>  0.262 ±0.003  ns/op
>> MethodHandleProxiesAsIFInstanceCall.direct avgt   15 
>>  0.264 ±0.005  ns/op
>> MethodHandleProxiesAsIFInstanceCreate.createCallInterfaceInstance  avgt   15 
>> 18.000 ±0.181  ns/op
>> MethodHandleProxiesAsIFInstanceCreate.createCallLambda avgt   15 
>>  17624.673 ± 2404.853  ns/op
>> MethodHandleProxiesAsIFInstanceCreate.createInterfaceInstance  avgt   15 
>> 17.554 ±0.748  ns/op
>> MethodHandleProxiesAsIFInstanceCreate.createLambda avgt   15 
>>  16860.341 ± 1270.982  ns/op
>> MethodHandleProxiesSuppl.testInstanceTargetavgt   15 
>>  0.405 ±0.006  ns/op
>> MethodHandleProxiesSuppl.testInstanceType  avgt   15 
>>  0.343 ±0.005  ns/op
>> MethodHandleProxiesSuppl.testIsWrapperInstance avgt   15 
>>  0.375 ±0.021  ns/op
>> 
>> 
>> Additionally, an obsolete `ProxyForMethodHandle` test was removed, for it's 
>> no longer applicable.
>> 
>> [^1]: single abstract method
>
> Chen Liang has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Remove assertion, no longer true with teleport definition in MHP

src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java line 342:

> 340: 
> 341: // individual handle fields
> 342: clb.withField(ORIGINAL_TARGET_NAME, CD_MethodHandle, 
> ACC_PRIVATE | ACC_FINAL);

Would a @Stable field help here? E.g if the returned functional interface 
instance is stored in a `static final` field, it should enable better 
performance?

-

PR Review Comment: https://git.openjdk.org/jdk/pull/13197#discussion_r1187237878


Re: RFR: 6983726: Reimplement MethodHandleProxies.asInterfaceInstance [v16]

2023-05-07 Thread Chen Liang
> As John Rose has pointed out in this issue, the current j.l.r.Proxy based 
> implementation of MethodHandleProxies.asInterface has a few issues:
> 1. Exposes too much information via Proxy supertype (and WrapperInstance 
> interface)
> 2. Does not allow future expansion to support SAM[^1] abstract classes
> 3. Slow (in fact, very slow)
> 
> This patch addresses all 3 problems:
> 1. It updates the WrapperInstance methods to take an `Empty` to avoid method 
> clashes
> 2. This patch obtains already generated classes from a ClassValue by the 
> requested interface type; the ClassValue can later be updated to compute 
> implementation generation for abstract classes as well.
> 3. This patch's faster than old implementation in general.
> 
> 
> Benchmark  Mode  Cnt  
> Score  Error  Units
> MethodHandleProxiesAsIFInstance.baselineAllocCompute   avgt   15  
> 1.483 ±0.025  ns/op
> MethodHandleProxiesAsIFInstance.baselineComputeavgt   15  
> 0.264 ±0.006  ns/op
> MethodHandleProxiesAsIFInstance.testCall   avgt   15  
> 1.773 ±0.040  ns/op
> MethodHandleProxiesAsIFInstance.testCreate avgt   15  
>16.754 ±0.411  ns/op
> MethodHandleProxiesAsIFInstance.testCreateCall avgt   15  
>19.609 ±1.598  ns/op
> MethodHandleProxiesAsIFInstanceCall.callDoable avgt   15  
> 0.424 ±0.024  ns/op
> MethodHandleProxiesAsIFInstanceCall.callHandle avgt   15  
> 1.936 ±0.008  ns/op
> MethodHandleProxiesAsIFInstanceCall.callInterfaceInstance  avgt   15  
> 1.766 ±0.014  ns/op
> MethodHandleProxiesAsIFInstanceCall.callLambda avgt   15  
> 0.414 ±0.005  ns/op
> MethodHandleProxiesAsIFInstanceCall.constantDoable avgt   15  
> 0.271 ±0.006  ns/op
> MethodHandleProxiesAsIFInstanceCall.constantHandle avgt   15  
> 0.263 ±0.004  ns/op
> MethodHandleProxiesAsIFInstanceCall.constantInterfaceInstance  avgt   15  
> 0.266 ±0.005  ns/op
> MethodHandleProxiesAsIFInstanceCall.constantLambda avgt   15  
> 0.262 ±0.003  ns/op
> MethodHandleProxiesAsIFInstanceCall.direct avgt   15  
> 0.264 ±0.005  ns/op
> MethodHandleProxiesAsIFInstanceCreate.createCallInterfaceInstance  avgt   15  
>18.000 ±0.181  ns/op
> MethodHandleProxiesAsIFInstanceCreate.createCallLambda avgt   15  
> 17624.673 ± 2404.853  ns/op
> MethodHandleProxiesAsIFInstanceCreate.createInterfaceInstance  avgt   15  
>17.554 ±0.748  ns/op
> MethodHandleProxiesAsIFInstanceCreate.createLambda avgt   15  
> 16860.341 ± 1270.982  ns/op
> MethodHandleProxiesSuppl.testInstanceTargetavgt   15  
> 0.405 ±0.006  ns/op
> MethodHandleProxiesSuppl.testInstanceType  avgt   15  
> 0.343 ±0.005  ns/op
> MethodHandleProxiesSuppl.testIsWrapperInstance avgt   15  
> 0.375 ±0.021  ns/op
> 
> 
> Additionally, an obsolete `ProxyForMethodHandle` test was removed, for it's 
> no longer applicable.
> 
> [^1]: single abstract method

Chen Liang has updated the pull request incrementally with one additional 
commit since the last revision:

  Remove assertion, no longer true with teleport definition in MHP

-

Changes:
  - all: https://git.openjdk.org/jdk/pull/13197/files
  - new: https://git.openjdk.org/jdk/pull/13197/files/836d9d0b..bd21e68e

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk=13197=15
 - incr: https://webrevs.openjdk.org/?repo=jdk=13197=14-15

  Stats: 2 lines in 1 file changed: 0 ins; 2 del; 0 mod
  Patch: https://git.openjdk.org/jdk/pull/13197.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/13197/head:pull/13197

PR: https://git.openjdk.org/jdk/pull/13197