Description
Context: dotnet/runtime#65853
generator
emits "JNI Marshal Methods", which are methods to be called by Java/JNI, which marshals parameters and return types in order to "forward" to virtual method overrides:
As these methods are intended to only be called by Java, it would make sense to apply the UnmanagedCallersOnlyAttribute
custom attribute to them. This wouldn't be immediately useful, but would permit future optimization opportunities.
Unfortunately, "just" adding [UnmanagedCallersOnly]
to generator
output is insufficient:
If you call
GetFunctionPointerForDelegate
on this delegate, you would end up doing the transition twice, so you'd end up in the right GC mode afterwards, but it might put the runtime into a weird state as it would transition from native to managed twice and then from managed to native twice.
which just sounds Bad™.
Thus, in order to use [UnmanagedCallersOnly]
, we would also need to:
-
Stop using System.Reflection.Emit /
JNINativeWrapper.CreateDelegate()
entirely (which might halt this entire thought process), as[UnmanagedCallersOnly]
can't be called by managed code. -
Turn
JniNativeMethodRegistration.Marshaler
into a "union", so that it can be either aDelegate
or an `IntPtr.Can that even be done without breaking ABI?
-
Update JNI marshal method lookup…somehow… so that the looked-up method uses
RuntimeMethodHandle.GetFunctionPointer()
to setJniNativeMethodRegistration.Marshaler
-as-IntPtr
instead of -as-Delegate
. (Plus figure out howRegisterNativeMembers()
is supposed to know when it should be using theDelegate
codepath vs. theIntPtr
codepath…)