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.
* [runtime] Call into managed code to handle runtime exceptions.
This makes things easier for CoreCLR.
There should be no significant performance hits; this code path is
exceptional, and exceptions are already very heavy-weight anyways.
* Update to use xamarin_free instead of mono_free as per review.
* Port more to managed code.
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>
The implementation will be completely different, where the hook into CoreCLR
is in managed code.
We still need to initialize the framework_peer_release_lock mutex, so move
that code out of gc_enable_new_refcount.
We need to call coreclr_initialize/monovm_initialize at startup, so do that.
This is a partial implementation, in that we're not setting all the properties
that we should, and also the PINVOKE_OVERRIDE callback is not doing everything
it should either yet.
Ref: #10504.
Move the creation of an uninitialized NSObject from native to managed, which:
* Removes the need for the mono_object_new Embedding API.
* Removes one location where we write to managed memory from native code (to
write the handle + flags in the uninitialized NSObject).
* Makes things easier for CoreCLR.
Any performance difference will be neglible compared to running the GC, so
there's no compelling reason to use the embedding API.
This makes things a bit easier with CoreCLR, since the new code works there too.
This also required a few changes in delegates.t4 to make code generation for
functions without arguments work correctly.
`calloc` can return `null` and we're writing to the memory location
which would crash the process.
An `OutOfMemoryException` is the correct way to handle this (even if
will likely crash the process anyway).
* [Foundation] Add an NSArray.FromNSObjects overload that can take an array of INativeObjects.
* [runtime] Use mono_array_setref instead of mono_array_set.
Otherwise the GC won't know about the assignment, and the assigned value can
be freed if it's no longer referenced anywhere else.
* Add optional mono_dangerous_add_raw_internal_call to exports.t4
* Use mono_dangerous_add_raw_internal_call on watchOS for icall registration
Internal calls added with mono_dangerous_add_raw_internal_call run in GC Unsafe
mode under cooperative and hybrid suspend, whereas internal calls added with
mono_add_internal_call run in GC Safe mode since
mono/mono@5756ba4b46 in order for hybrid suspend
to be a transparent replacement for preemptive suspend (the old default). The
icalls in GC Unsafe mode have a responsibility not to block indefinitely
without manually performing a thread state transition to GC Safe mode, and in
return they avoid a thread state transition when the icall is invoked from a
managed method.
`mono_jit_set_aot_only` is deprecated and accidentally broke with
https://github.com/mono/mono/pull/7887
This should fix device tests with `mono-2018-06`
This makes exception marshaling work with Xamarin.Mac apps that use the system
mono (such as Visual Studio for Mac, and assuming at least a v5.12 system
mono).
https://github.com/xamarin/xamarin-macios/issues/4271
mono_set_pending_exception is a private mono symbol, which means we won't find
it when using the system mono (as a dynamic library). In that case, we'd
abort.
Instead try to call mono_raise_exception, and hope for the best. It will leak
somewhat, but that's still better than asserting.
This changes the generated wrapper function from:
```c
MONO_API void
mono_set_pending_exception (MonoException * exc)
{
if (mono_set_pending_exception_func == NULL)
xamarin_assertion_message ("Could not load mono_set_pending_exception\n");
return mono_set_pending_exception_func (exc);
}
```
to
```c
MONO_API void
mono_set_pending_exception (MonoException * exc)
{
if (mono_set_pending_exception_func == NULL)
return mono_raise_exception (exc);
return mono_set_pending_exception_func (exc);
}
```
Also this only applies to Xamarin.Mac apps that use the system mono (such as VSfM).
https://bugzilla.xamarin.com/show_bug.cgi?id=59979
The two functions mono_class_is_nullable and mono_class_get_nullable_param are
private mono symbols, which means we can't call them when using Xamarin.Mac
with libmono from a dynamic library.
Implement a fallback for this case, where we call a managed method when these
functions are not available (and restrict this workaround to Xamarin.Mac only,
since it's not needed for Xamarin.iOS).
* [runtime] Fix broken indentation to make code less confusing.
* [runtime] Rework initialization for Xamarin.Mac extensions.
1. Delay the Application.Init execution from step 6 in the initialization
sequence, to when we'd run the managed Main function for a normal app. This
makes the code a bit easier to reason about, since both code paths behave
more similar. It's also matches the initialization documentation better
(step 6 is "find the executable", not "find the executable and run
Application.Init").
2. Install custom callbacks for mono's logging function just before calling
Application.Init. We already install these custom callbacks in
xamarin_initialize, but that doesn't help much if something goes wrong
before xamarin_initialize is called (and there's no harm in doing this
twice).
3. Treat the extension dll as an entry assembly, make the path to the entry
assembly available to managed code, and load this assembly if
Assembly.GetEntryAssembly can't find it (which happens for extensions,
since there's no entry point as Assembly.GetEntryAssembly defines an entry
assembly).
This fixes launching of Xamarin.Mac extensions.
* [runtime] Spaces -> tabs.
Managed exception marshaling interferes with the debugger, because it adds
exception handlers to executing code, which makes the Mono runtime think an
exception is handled when logically it's not (although technically it is).
The consequence is that the IDEs will only be notified when we re-throw the
exception after catching it, making it impossible for the IDEs to stop when
the exception is thrown (they will instead stop when we re-throw the
exception).
So disable managed exception marshaling (unless the user changed the default
behavior) when a debugger is attached.
This is the same behavior as Xamarin.Android.
https://bugzilla.xamarin.com/show_bug.cgi?id=45116
The base directory and config file name is normally set automatically
when we ask Mono to execute the Main function, but in the case of extensions,
there is no Main function, so these values are not set, causing some
features (reflection-only assembly load) to not work correctly.
https://bugzilla.xamarin.com/show_bug.cgi?id=42784