2021-03-18 09:23:39 +03:00
/ * - * - Mode : C ; tab - width : 8 ; indent - tabs - mode : t ; c - basic - offset : 8 - * - * /
/ *
* Authors : Rolf Bjarne Kvinge
*
* Copyright ( C ) 2021 Microsoft Corp .
*
* /
/ * Support code for using MonoVM * /
# if ! defined ( CORECLR_RUNTIME )
# include < TargetConditionals . h >
2021-04-21 17:21:09 +03:00
# include < pthread . h >
2021-03-18 09:23:39 +03:00
# if ! DOTNET && TARGET_OS _OSX
# define LEGACY_XAMARIN _MAC 1
# else
# define LEGACY_XAMARIN _MAC 0
# endif
2021-03-25 09:25:20 +03:00
# include "product.h"
2021-03-18 09:23:39 +03:00
# include "monotouch-debug.h"
# include "runtime-internal.h"
# include "xamarin/xamarin.h"
# include "xamarin/monovm-bridge.h"
2021-03-25 09:25:20 +03:00
static MonoAssembly * entry_assembly = NULL ;
static MonoClass * inativeobject_class = NULL ;
static MonoClass * nsobject_class = NULL ;
static MonoClass * nsvalue_class = NULL ;
static MonoClass * nsnumber_class = NULL ;
static MonoClass * nsstring_class = NULL ;
static MonoClass * runtime_class = NULL ;
2021-03-18 09:23:39 +03:00
# if ! LEGACY_XAMARIN _MAC
void
xamarin_bridge _setup ( )
{
const char * c_bundle _path = xamarin_get _bundle _path ( ) ;
setenv ( "MONO_PATH" , c_bundle _path , 1 ) ;
setenv ( "MONO_XMLSERIALIZER_THS" , "no" , 1 ) ;
setenv ( "MONO_REFLECTION_SERIALIZER" , "yes" , 1 ) ;
# if TARGET_OS _WATCH || TARGET_OS _TV
mini_parse _debug _option ( "explicit-null-checks" ) ;
# endif
// see http : // bugzilla . xamarin . com / show_bug . cgi ? id = 820
// take this line out once the bug is fixed
mini_parse _debug _option ( "no-gdb-backtrace" ) ;
}
void
xamarin_bridge _initialize ( )
{
# if defined ( __arm __ ) || defined ( __aarch64 __ )
xamarin_register _modules ( ) ;
# endif
DEBUG_LAUNCH _TIME _PRINT ( "\tAOT register time" ) ;
# ifdef DEBUG
monotouch_start _debugging ( ) ;
DEBUG_LAUNCH _TIME _PRINT ( "\tDebug init time" ) ;
# endif
if ( xamarin_init _mono _debug )
mono_debug _init ( MONO_DEBUG _FORMAT _MONO ) ;
mono_install _assembly _preload _hook ( xamarin_assembly _preload _hook , NULL ) ;
mono_install _load _aot _data _hook ( xamarin_load _aot _data , xamarin_free _aot _data , NULL ) ;
# ifdef DEBUG
monotouch_start _profiling ( ) ;
DEBUG_LAUNCH _TIME _PRINT ( "\tProfiler config time" ) ;
# endif
mono_set _signal _chaining ( TRUE ) ;
mono_set _crash _chaining ( TRUE ) ;
mono_install _unhandled _exception _hook ( xamarin_unhandled _exception _handler , NULL ) ;
mono_install _ftnptr _eh _callback ( xamarin_ftnptr _exception _handler ) ;
mono_jit _init _version ( "MonoTouch" , "mobile" ) ;
/ *
As part of mono initialization a preload hook is added that overrides ours , so we need to re - instate it here .
This is wasteful , but there ' s no way to manipulate the preload hook list except by adding to it .
* /
mono_install _assembly _preload _hook ( xamarin_assembly _preload _hook , NULL ) ;
DEBUG_LAUNCH _TIME _PRINT ( "\tJIT init time" ) ;
}
# endif // ! LEGACY_XAMARIN _MAC
2021-03-25 09:25:20 +03:00
static MonoClass *
get_class _from _name ( MonoImage * image , const char * nmspace , const char * name , bool optional = false )
{
// COOP : this is a convenience function executed only at startup , I believe the mode here doesn ' t matter .
MonoClass * rv = mono_class _from _name ( image , nmspace , name ) ;
if ( ! rv && ! optional )
xamarin_assertion _message ( "Fatal error: failed to load the class '%s.%s'\n." , nmspace , name ) ;
return rv ;
}
void
xamarin_bridge _call _runtime _initialize ( struct InitializationOptions * options , GCHandle * exception_gchandle )
{
MonoMethod * runtime_initialize ;
void * params [ 2 ] ;
MonoObject * exc = NULL ;
MonoImage * platform_image = NULL ;
entry_assembly = xamarin_open _assembly ( PRODUCT_DUAL _ASSEMBLY ) ;
if ( ! entry_assembly )
xamarin_assertion _message ( "Failed to load %s." , PRODUCT_DUAL _ASSEMBLY ) ;
platform_image = mono_assembly _get _image ( entry_assembly ) ;
const char * objcruntime = "ObjCRuntime" ;
const char * foundation = "Foundation" ;
runtime_class = get_class _from _name ( platform_image , objcruntime , "Runtime" ) ;
inativeobject_class = get_class _from _name ( platform_image , objcruntime , "INativeObject" ) ;
nsobject_class = get_class _from _name ( platform_image , foundation , "NSObject" ) ;
nsnumber_class = get_class _from _name ( platform_image , foundation , "NSNumber" , true ) ;
nsvalue_class = get_class _from _name ( platform_image , foundation , "NSValue" , true ) ;
nsstring_class = get_class _from _name ( platform_image , foundation , "NSString" , true ) ;
runtime_initialize = mono_class _get _method _from _name ( runtime_class , "Initialize" , 1 ) ;
if ( runtime_initialize = = NULL )
xamarin_assertion _message ( "Fatal error: failed to load the %s.%s method" , "Runtime" , "Initialize" ) ;
params [ 0 ] = options ;
mono_runtime _invoke ( runtime_initialize , NULL , params , & exc ) ;
if ( exc )
* exception_gchandle = xamarin_gchandle _new ( exc , false ) ;
}
void
xamarin_bridge _register _product _assembly ( GCHandle * exception_gchandle )
{
xamarin_register _monoassembly ( entry_assembly , exception_gchandle ) ;
2021-03-22 14:53:52 +03:00
// We don ' t need the entry_assembly around anymore , so release it .
xamarin_mono _object _release ( & entry_assembly ) ;
2021-03-25 09:25:20 +03:00
}
2021-04-30 08:49:25 +03:00
MonoMethod *
xamarin_bridge _get _mono _method ( MonoReflectionMethod * method )
{
// COOP : Reads managed memory , needs to be in UNSAFE mode
MONO_ASSERT _GC _UNSAFE ;
PublicMonoReflectionMethod * rm = ( PublicMonoReflectionMethod * ) method ;
return rm -> method ;
}
2021-03-25 09:25:20 +03:00
MonoClass *
xamarin_get _inativeobject _class ( )
{
if ( inativeobject_class = = NULL )
xamarin_assertion _message ( "Internal consistency error, please file a bug (https://github.com/xamarin/xamarin-macios/issues/new). Additional data: can't get the %s class because it's been linked away.\n" , "INativeObject" ) ;
return inativeobject_class ;
}
MonoClass *
xamarin_get _nsobject _class ( )
{
if ( nsobject_class = = NULL )
xamarin_assertion _message ( "Internal consistency error, please file a bug (https://github.com/xamarin/xamarin-macios/issues/new). Additional data: can't get the %s class because it's been linked away.\n" , "NSObject" ) ;
return nsobject_class ;
}
MonoClass *
xamarin_get _nsvalue _class ( )
{
if ( nsvalue_class = = NULL )
xamarin_assertion _message ( "Internal consistency error, please file a bug (https://github.com/xamarin/xamarin-macios/issues/new). Additional data: can't get the %s class because it's been linked away.\n" , "NSValue" ) ;
return nsvalue_class ;
}
MonoClass *
xamarin_get _nsnumber _class ( )
{
if ( nsnumber_class = = NULL )
xamarin_assertion _message ( "Internal consistency error, please file a bug (https://github.com/xamarin/xamarin-macios/issues/new). Additional data: can't get the %s class because it's been linked away.\n" , "NSNumber" ) ;
return nsnumber_class ;
}
MonoClass *
xamarin_get _nsstring _class ( )
{
if ( nsstring_class = = NULL )
xamarin_assertion _message ( "Internal consistency error, please file a bug (https://github.com/xamarin/xamarin-macios/issues/new). Additional data: can't get the %s class because it's been linked away.\n" , "NSString" ) ;
return nsstring_class ;
}
MonoClass *
xamarin_get _runtime _class ( )
{
if ( runtime_class = = NULL )
xamarin_assertion _message ( "Internal consistency error, please file a bug (https://github.com/xamarin/xamarin-macios/issues/new). Additional data: can't get the %s class because it's been linked away.\n" , "Runtime" ) ;
return runtime_class ;
}
2021-04-21 17:21:09 +03:00
/ * Wrapping threads with NSAutoreleasePool
*
* We must create an NSAutoreleasePool for each thread , so users
* don ' t have to do it manually .
*
* Use mono ' s profiling API to get notified for thread start / stop ,
* and create a pool that spans the thread ' s entire lifetime .
* /
static CFMutableDictionaryRef xamarin_thread _hash = NULL ;
static pthread_mutex _t thread_hash _lock = PTHREAD_MUTEX _INITIALIZER ;
static void
xamarin_thread _start ( void * user_data )
{
// COOP : no managed memory access : any mode . Switching to safe mode since we ' re locking a mutex .
NSAutoreleasePool * pool ;
if ( mono_thread _is _foreign ( mono_thread _current ( ) ) )
return ;
MONO_ENTER _GC _SAFE ;
pool = [ [ NSAutoreleasePool alloc ] init ] ;
pthread_mutex _lock ( & thread_hash _lock ) ;
CFDictionarySetValue ( xamarin_thread _hash , GINT_TO _POINTER ( pthread_self ( ) ) , pool ) ;
pthread_mutex _unlock ( & thread_hash _lock ) ;
MONO_EXIT _GC _SAFE ;
}
static void
xamarin_thread _finish ( void * user_data )
{
// COOP : no managed memory access : any mode . Switching to safe mode since we ' re locking a mutex .
NSAutoreleasePool * pool ;
MONO_ENTER _GC _SAFE ;
/ * Don ' t drain the pool while holding the thread hash lock . * /
pthread_mutex _lock ( & thread_hash _lock ) ;
pool = ( NSAutoreleasePool * ) CFDictionaryGetValue ( xamarin_thread _hash , GINT_TO _POINTER ( pthread_self ( ) ) ) ;
if ( pool )
CFDictionaryRemoveValue ( xamarin_thread _hash , GINT_TO _POINTER ( pthread_self ( ) ) ) ;
pthread_mutex _unlock ( & thread_hash _lock ) ;
if ( pool )
[ pool drain ] ;
MONO_EXIT _GC _SAFE ;
}
static void
thread_start ( MonoProfiler * prof , uintptr_t tid )
{
// COOP : no managed memory access : any mode .
xamarin_thread _start ( NULL ) ;
}
static void
thread_end ( MonoProfiler * prof , uintptr_t tid )
{
// COOP : no managed memory access : any mode .
xamarin_thread _finish ( NULL ) ;
}
void
xamarin_install _nsautoreleasepool _hooks ( )
{
// COOP : executed at startup ( and no managed memory access ) : any mode .
xamarin_thread _hash = CFDictionaryCreateMutable ( kCFAllocatorDefault , 0 , NULL , NULL ) ;
mono_profiler _install _thread ( thread_start , thread_end ) ;
}
2021-05-06 17:19:59 +03:00
void
xamarin_bridge _free _mono _signature ( MonoMethodSignature * * psig )
{
// nothing to free here
* psig = NULL ;
}
2021-03-22 10:04:56 +03:00
# if DOTNET
bool
xamarin_bridge _vm _initialize ( int propertyCount , const char * * propertyKeys , const char * * propertyValues )
{
int rv ;
rv = monovm_initialize ( propertyCount , propertyKeys , propertyValues ) ;
LOG_MONOVM ( stderr , "xamarin_vm_initialize (%i, %p, %p): rv: %i\n" , propertyCount , propertyKeys , propertyValues , rv ) ;
return rv = = 0 ;
}
2021-05-06 08:25:43 +03:00
// We have a P / Invoke to xamarin_mono _object _retain in managed code , but the
// corresponding native method only really exists when using CoreCLR . However ,
// the P / Invoke might not always be linked away ( if the linker isn ' t enabled
// for instance ) , in which case we must still have a native function . So
// provide an empty implementation of xamarin_mono _object _retain ( since it
// doesn ' t have to do anything when using MonoVM ) . We still keep the # define
// that does nothing , so that all the native code that calls
// xamarin_mono _object _retain , will completely disappear when using MonoVM .
# undef xamarin_mono _object _retain
extern "C" {
void xamarin_mono _object _retain ( MonoObject * mobj ) ;
}
void
xamarin_mono _object _retain ( MonoObject * mobj )
{
// Nothing to do here
}
2021-03-22 10:04:56 +03:00
# endif // DOTNET
2021-03-18 09:23:39 +03:00
# endif // ! CORECLR_RUNTIME