Skip to content

Commit

Permalink
[Java.Interop] Avoid some method group conversions
Browse files Browse the repository at this point in the history
Context: https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#improved-method-group-conversion-to-delegate
Context: dotnet#1034
Context: dotnet/roslyn#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.
  • Loading branch information
jonpryor committed Oct 11, 2022
1 parent 16e1ecd commit 231623c
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 5 deletions.
6 changes: 3 additions & 3 deletions src/Java.Interop/Java.Interop/JavaProxyObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ sealed class JavaProxyObject : JavaObject, IEquatable<JavaProxyObject>
[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 {
Expand Down
4 changes: 2 additions & 2 deletions src/Java.Interop/Java.Interop/ManagedPeer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ static ManagedPeer ()
new JniNativeMethodRegistration (
"construct",
ConstructSignature,
(ConstructMarshalMethod) Construct),
new ConstructMarshalMethod (Construct)),
new JniNativeMethodRegistration (
"registerNativeMembers",
RegisterNativeMembersSignature,
(RegisterMarshalMethod) RegisterNativeMembers)
new RegisterMarshalMethod (RegisterNativeMembers))
);
}

Expand Down

0 comments on commit 231623c

Please sign in to comment.