Since NativeAOT generates native libraries and executables that do not
rely on assemblies they were compiled from, all managed assemblies can
be excluded from the application bundle.
This reduces the size of the application bundle by `3,17Mb` (or ~19%
compared to the baseline)
| MAUI ios app | Base | This PR | diff (%) |
|--------------|-----------|-----------|----------|
| SOD (Mb) | 50,13 | 41,93 | -16,3% |
| .ipa (Mb) | 16,59 | 13,43 | -19% |
Fixes: https://github.com/xamarin/xamarin-macios/issues/18472
This makes it possible to simplify and remove a good chunk of related code.
Especially for CoreCLR this should be a minor perf improvement, because we'll do fewer transitions between managed and native code.
* We now create a tracking GCHandle for all NSObjects, not only the toggled ones.
CoreCLR will notify us when a tracked GCHandle's target enters finalization, and
we need to be notified for all NSObjects, not just the toggled ones.
* Augment the tracking callback to know about non-toggled objects, and in that
case report that the tracking GCHandle is a weak GCHandle.
* There's no need to store the tracking GCHandle in a field in the NSObject instance,
since we store it in our runtime object_map.
* Remove one place where we set the InFinalizerQueue flag, since it's no longer
required there (this reverts a previous attempt at fixing this problem - 0622ae4af2)
- we only set the InFinalizerQueue flag in the xamarin_coreclr_reference_tracking_tracked_object_entered_finalization
callback now.
* Update a few comments accordingly.
Partial fix for https://github.com/xamarin/xamarin-macios/issues/13531.
Fixes https://github.com/xamarin/xamarin-macios/issues/13921 (again).
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.