We need to process the runtimeconfig.json file somehow when using CoreCLR, and
the embedding API we use (coreclr_initialize) won't parse it for us. So re-use
the logic we already have to process runtimeconfig.json for MonoVM (which
involves converting it to a binary format at build time, which we then process
at runtime).
To have consistent behavior in .NET, set the current directory to the root of
the app bundle for all platforms.
This is a breaking change for legacy Xamarin.Mac, which used to set the
current directory to the Contents/Resources subdirectory, but there's a simple
workaround for customers that depend on the old behavior (change it in Main
themselves), and I believe the consistent experience across platforms warrants
this change.
Note that we already had a breaking change here for macOS/.NET: we were
(unintentionally) setting the current directory to the Contents/MonoBundle
directory, which neither matched mobile platforms, nor the legacy Xamarin.Mac
behavior.
This solves the problem of what to do for Mac Catalyst apps, because there's
no need to choose between the macOS or the mobile behavior, since they're the
same.
This required changing the launch of macOS apps using CoreCLR to pass the full
path to the entry assembly, since the entry assembly isn't in the current
directory anymore.
The code contains comments explaining the new behavior.
Some tests that poked into the private 'flags' field on NSObject had to be
updated, because the field is now named differently in .NET.
I also added two more tests for toggle ref scenarios.
Before:
There were 258096 MonoObjects created, 246948 MonoObjects freed, so 11148 were not freed. (dynamic registrar)
There were 205834 MonoObjects created, 205214 MonoObjects freed, so 620 were not freed. (static registrar)
After:
There were 205834 MonoObjects created, 205222 MonoObjects freed, so 612 were not freed. (dynamic registrar)
There were 258100 MonoObjects created, 258019 MonoObjects freed, so 81 were not freed. (static registrar)
* If the return value from xamarin_get_reflection_method_method is cached in a
static variable, we can only release at process exist.
* Otherwise just release at the end of the current method.
Before:
There were 258096 MonoObjects created, 246948 MonoObjects freed, so 11148 were not freed. (dynamic registrar)
There were 205834 MonoObjects created, 205214 MonoObjects freed, so 620 were not freed. (static registrar)
After:
There were 258092 MonoObjects created, 246945 MonoObjects freed, so 11147 were not freed. (dynamic registrar)
There were 205834 MonoObjects created, 205600 MonoObjects freed, so 234 were not freed. (static registrar)
* [runtime] Add support for exception marshalling to CoreCLR.
* [runtime] Add an empty implementation of the toggle ref machinery.
We need this to use the unhandled exception handler support in CoreCLR,
because the ObjectiveCMarshal.Initialize call to initialize unhandled
exception support requires passing toggle ref callbacks as well.
* [tests] The TestConstrainedGenericType test can now be re-enabled, after a few updates.
* [runtime] Add support for tracking created and destroyed MonoObject* instances for CoreCLR.
Implement a rudimentary way of tracking created and destroyed MonoObject*
instances, so that it's easy to find leaks.
* Add a xamarin_bridge_shutdown method that's called just before returning from xamarin_main.
And use it to dump the leaked MonoObject*s.
* Remove a few unused xamarin_get_*_class functions.
* Make the remaining two (xamarin_get_[nsnumber|nsvalue]_type) return a
MonoType* instead of MonoClass* - that makes things slightly simpler for
CoreCLR (the MonoClass* return values from the previous functions were
always converted to MonoType*s anyway).
* Implement the xamarin_get_[nsnumber|nsvalue]_type functions.
* Make the existing mono_get_string_class use the new (and more generic)
xamarin_bridge_lookup_class method instead of the specific
xamarin_bridge_get_string_class (which can now be removed).
We need additional API in CoreCLR to support pending exception properly, and
this is in progress [1]. In the meantime, stub out parts of it, so that the
process doesn't abort. This way we'll have failing tests instead (and work in
other areas can progress, since the process doesn't abort).
[1]: https://github.com/dotnet/runtime/pull/52146
When using the MonoVM, we compare MonoClass instances by pointer. This turns
out a bit complicated for CoreCLR, because our MonoClass instances are not
unique (there can be multiple MonoClass instances that refer to the same
type), so instead implement helper methods that do the comparison. This also
has the benefit of not requiring any memory allocations on CoreCLR.
* The generated static registration code will eventually be different.
* The generated code has to be compiled with different compiler flags.
This also required adding a new overload of xamarin_mono_object_release for the generated
code to compile.
This also meant reviewing calling code to make sure that MonoObject*s are
released when they should be, which meant reviewing every method that returns
a MonoObject*, and release the result.
This required adding a helper method to get the assembly name for a given
MonoAssembly, since that's what CoreCLR uses to determine what to execute.
Co-authored-by: Manuel de la Pena <mandel@microsoft.com>