From f498fcf543b54a805c9665d7c8f1dcee74ced0cc Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 11 Oct 2022 14:31:01 -0400 Subject: [PATCH] [Java.Interop] Avoid some method group conversions (#1050) Context: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#improved-method-group-conversion-to-delegate Context: https://github.com/xamarin/java.interop/issues/1034 Context: https://github.com/dotnet/roslyn/issues/62832 C#11 introduced a "slight semantic" change with "Improved method group conversion to delegate": > The C# 11 compiler caches the delegate object created from a method > group conversion and reuses that single delegate object. The result of optimization is that for current `generator`-emitted code such as: static Delegate GetFooHandler () { if (cb_foo == null) cb_foo = JNINativeWrapper.CreateDelegate ((_JniMarshal_PP_V) n_Foo); return cb_foo; } The `(_JniMarshal_PP_V) n_Foo` expression is a "method group conversion", and under C#11 the generated IL is *larger*, as the delegate instance is *cached* in case it is needed again. However in *our* case we *know* the delegate instance won't be needed again, not in this scope, so all this "optimization" does *for us* is increase the size of our binding assemblies when built under C#11. Review `src/Java.Interop` for use of `new JniNativeMethodRegistration` and replace "cast-style" method group conversions `(D) M` to "new-style" delegate conversions `new D(M)`. This explicitly "opts-out" of the C#11 optimization. --- src/Java.Interop/Java.Interop/JavaProxyObject.cs | 6 +++--- src/Java.Interop/Java.Interop/ManagedPeer.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Java.Interop/Java.Interop/JavaProxyObject.cs b/src/Java.Interop/Java.Interop/JavaProxyObject.cs index 5454185b0..beb3567d5 100644 --- a/src/Java.Interop/Java.Interop/JavaProxyObject.cs +++ b/src/Java.Interop/Java.Interop/JavaProxyObject.cs @@ -17,9 +17,9 @@ sealed class JavaProxyObject : JavaObject, IEquatable [JniAddNativeMethodRegistrationAttribute] static void RegisterNativeMembers (JniNativeMethodRegistrationArguments args) { - args.Registrations.Add (new JniNativeMethodRegistration ("equals", "(Ljava/lang/Object;)Z", (EqualsMarshalMethod)Equals)); - args.Registrations.Add (new JniNativeMethodRegistration ("hashCode", "()I", (GetHashCodeMarshalMethod)GetHashCode)); - args.Registrations.Add (new JniNativeMethodRegistration ("toString", "()Ljava/lang/String;", (ToStringMarshalMethod)ToString)); + args.Registrations.Add (new JniNativeMethodRegistration ("equals", "(Ljava/lang/Object;)Z", new EqualsMarshalMethod (Equals))); + args.Registrations.Add (new JniNativeMethodRegistration ("hashCode", "()I", new GetHashCodeMarshalMethod (GetHashCode))); + args.Registrations.Add (new JniNativeMethodRegistration ("toString", "()Ljava/lang/String;", new ToStringMarshalMethod (ToString))); } public override JniPeerMembers JniPeerMembers { diff --git a/src/Java.Interop/Java.Interop/ManagedPeer.cs b/src/Java.Interop/Java.Interop/ManagedPeer.cs index 560008bf3..eb43a9e85 100644 --- a/src/Java.Interop/Java.Interop/ManagedPeer.cs +++ b/src/Java.Interop/Java.Interop/ManagedPeer.cs @@ -25,11 +25,11 @@ static ManagedPeer () new JniNativeMethodRegistration ( "construct", ConstructSignature, - (ConstructMarshalMethod) Construct), + new ConstructMarshalMethod (Construct)), new JniNativeMethodRegistration ( "registerNativeMembers", RegisterNativeMembersSignature, - (RegisterMarshalMethod) RegisterNativeMembers) + new RegisterMarshalMethod (RegisterNativeMembers)) ); }