[runtime] Refactor the toggle ref code to separate MonoVM-specific code and generic logic. (#11616)
This makes it simpler to impement the toggle ref logic for CoreCLR once we can do that.
This commit is contained in:
Родитель
ee5e2f0b09
Коммит
f38187f054
|
@ -29,6 +29,12 @@ xamarin_bridge_initialize ()
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
xamarin_enable_new_refcount ()
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
bool
|
||||
xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues)
|
||||
{
|
||||
|
|
|
@ -240,7 +240,9 @@
|
|||
new Export ("void", "mono_profiler_install_gc",
|
||||
"MonoProfileGCFunc", "callback",
|
||||
"MonoProfileGCResizeFunc", "heap_resize_callback"
|
||||
),
|
||||
) {
|
||||
XamarinRuntime = RuntimeMode.MonoVM,
|
||||
},
|
||||
|
||||
new Export ("void", "mono_profiler_load",
|
||||
"const char *", "desc"
|
||||
|
@ -567,7 +569,9 @@
|
|||
new Export ("void", "mono_gc_toggleref_add",
|
||||
"MonoObject *", "object",
|
||||
"mono_bool", "strong_ref"
|
||||
),
|
||||
) {
|
||||
XamarinRuntime = RuntimeMode.MonoVM,
|
||||
},
|
||||
|
||||
new Export ("void", "mono_gc_toggleref_register_callback",
|
||||
"MonoToggleRefCallback", "process_toggleref"
|
||||
|
|
|
@ -419,4 +419,64 @@ xamarin_mono_object_retain (MonoObject *mobj)
|
|||
|
||||
#endif // DOTNET
|
||||
|
||||
/*
|
||||
* ToggleRef support
|
||||
*/
|
||||
// #define DEBUG_TOGGLEREF 1
|
||||
|
||||
static void
|
||||
gc_register_toggleref (MonoObject *obj, id self, bool isCustomType)
|
||||
{
|
||||
// COOP: This is an icall, at entry we're in unsafe mode. Managed memory is accessed, so we stay in unsafe mode.
|
||||
MONO_ASSERT_GC_UNSAFE;
|
||||
|
||||
#ifdef DEBUG_TOGGLEREF
|
||||
id handle = xamarin_get_nsobject_handle (obj);
|
||||
|
||||
PRINT ("**Registering object %p handle %p RC %d flags: %i isCustomType: %i",
|
||||
obj,
|
||||
handle,
|
||||
(int) (handle ? [handle retainCount] : 0),
|
||||
xamarin_get_nsobject_flags (obj),
|
||||
isCustomType
|
||||
);
|
||||
#endif
|
||||
mono_gc_toggleref_add (obj, TRUE);
|
||||
|
||||
// Make sure the GCHandle we have is a weak one for custom types.
|
||||
if (isCustomType) {
|
||||
MONO_ENTER_GC_SAFE;
|
||||
xamarin_switch_gchandle (self, true);
|
||||
MONO_EXIT_GC_SAFE;
|
||||
}
|
||||
}
|
||||
|
||||
static MonoToggleRefStatus
|
||||
gc_toggleref_callback (MonoObject *object)
|
||||
{
|
||||
// COOP: this is a callback called by the GC, so I assume the mode here doesn't matter
|
||||
MonoToggleRefStatus res;
|
||||
uint8_t flags = xamarin_get_nsobject_flags (object);
|
||||
|
||||
res = xamarin_gc_toggleref_callback (flags, NULL, xamarin_get_nsobject_handle, object);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
gc_event_callback (MonoProfiler *prof, MonoGCEvent event, int generation)
|
||||
{
|
||||
// COOP: this is a callback called by the GC, I believe the mode here doesn't matter.
|
||||
xamarin_gc_event (event);
|
||||
}
|
||||
|
||||
void
|
||||
xamarin_enable_new_refcount ()
|
||||
{
|
||||
mono_gc_toggleref_register_callback (gc_toggleref_callback);
|
||||
|
||||
xamarin_add_internal_call ("Foundation.NSObject::RegisterToggleRef", (const void *) gc_register_toggleref);
|
||||
mono_profiler_install_gc (gc_event_callback, NULL);
|
||||
}
|
||||
|
||||
#endif // !CORECLR_RUNTIME
|
||||
|
|
|
@ -796,51 +796,24 @@ xamarin_type_get_full_name (MonoType *type, GCHandle *exception_gchandle)
|
|||
* ToggleRef support
|
||||
*/
|
||||
// #define DEBUG_TOGGLEREF 1
|
||||
#if !defined (CORECLR_RUNTIME)
|
||||
static void
|
||||
gc_register_toggleref (MonoObject *obj, id self, bool isCustomType)
|
||||
{
|
||||
// COOP: This is an icall, at entry we're in unsafe mode. Managed memory is accessed, so we stay in unsafe mode.
|
||||
MONO_ASSERT_GC_UNSAFE;
|
||||
|
||||
#ifdef DEBUG_TOGGLEREF
|
||||
id handle = xamarin_get_nsobject_handle (obj);
|
||||
|
||||
PRINT ("**Registering object %p handle %p RC %d flags: %i isCustomType: %i",
|
||||
obj,
|
||||
handle,
|
||||
(int) (handle ? [handle retainCount] : 0),
|
||||
xamarin_get_nsobject_flags (obj),
|
||||
isCustomType
|
||||
);
|
||||
#endif
|
||||
mono_gc_toggleref_add (obj, TRUE);
|
||||
|
||||
// Make sure the GCHandle we have is a weak one for custom types.
|
||||
if (isCustomType) {
|
||||
MONO_ENTER_GC_SAFE;
|
||||
xamarin_switch_gchandle (self, true);
|
||||
MONO_EXIT_GC_SAFE;
|
||||
}
|
||||
}
|
||||
|
||||
static MonoToggleRefStatus
|
||||
gc_toggleref_callback (MonoObject *object)
|
||||
MonoToggleRefStatus
|
||||
xamarin_gc_toggleref_callback (uint8_t flags, id handle, xamarin_get_handle_func get_handle, MonoObject *info)
|
||||
{
|
||||
// COOP: this is a callback called by the GC, so I assume the mode here doesn't matter
|
||||
id handle = NULL;
|
||||
MonoToggleRefStatus res;
|
||||
|
||||
uint8_t flags = xamarin_get_nsobject_flags (object);
|
||||
bool disposed = (flags & NSObjectFlagsDisposed) == NSObjectFlagsDisposed;
|
||||
bool has_managed_ref = (flags & NSObjectFlagsHasManagedRef) == NSObjectFlagsHasManagedRef;
|
||||
|
||||
if (disposed || !has_managed_ref) {
|
||||
res = MONO_TOGGLE_REF_DROP; /* Already disposed, we don't need the managed object around */
|
||||
} else {
|
||||
handle = xamarin_get_nsobject_handle (object);
|
||||
if (handle == NULL)
|
||||
handle = get_handle (info);
|
||||
|
||||
if (handle == NULL) { /* This shouldn't really happen */
|
||||
return MONO_TOGGLE_REF_DROP;
|
||||
res = MONO_TOGGLE_REF_DROP;
|
||||
} else {
|
||||
if ([handle retainCount] == 1)
|
||||
res = MONO_TOGGLE_REF_WEAK;
|
||||
|
@ -861,21 +834,17 @@ gc_toggleref_callback (MonoObject *object)
|
|||
rv = "UNKNOWN";
|
||||
}
|
||||
const char *cn = NULL;
|
||||
if (handle == NULL) {
|
||||
cn = object_getClassName (xamarin_get_nsobject_handle (object));
|
||||
} else {
|
||||
cn = object_getClassName (handle);
|
||||
}
|
||||
if (handle == NULL)
|
||||
handle = get_handle (info);
|
||||
cn = object_getClassName (handle);
|
||||
PRINT ("\tinspecting %p handle:%p %s flags: %i RC %d -> %s\n", object, handle, cn, (int) flags, (int) (handle ? [handle retainCount] : 0), rv);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined (CORECLR_RUNTIME)
|
||||
static void
|
||||
gc_event_callback (MonoProfiler *prof, MonoGCEvent event, int generation)
|
||||
void
|
||||
xamarin_gc_event (MonoGCEvent event)
|
||||
{
|
||||
// COOP: this is a callback called by the GC, I believe the mode here doesn't matter.
|
||||
switch (event) {
|
||||
|
@ -892,16 +861,6 @@ gc_event_callback (MonoProfiler *prof, MonoGCEvent event, int generation)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gc_enable_new_refcount (void)
|
||||
{
|
||||
mono_gc_toggleref_register_callback (gc_toggleref_callback);
|
||||
|
||||
xamarin_add_internal_call ("Foundation.NSObject::RegisterToggleRef", (const void *) gc_register_toggleref);
|
||||
mono_profiler_install_gc (gc_event_callback, NULL);
|
||||
}
|
||||
#endif // !CORECLR_RUNTIME
|
||||
|
||||
#if !defined (CORECLR_RUNTIME)
|
||||
struct _MonoProfiler {
|
||||
int dummy;
|
||||
|
@ -1309,9 +1268,7 @@ xamarin_initialize ()
|
|||
pthread_mutex_init (&framework_peer_release_lock, &attr);
|
||||
pthread_mutexattr_destroy (&attr);
|
||||
|
||||
#if !defined (CORECLR_RUNTIME)
|
||||
gc_enable_new_refcount ();
|
||||
#endif
|
||||
xamarin_enable_new_refcount ();
|
||||
|
||||
MONO_EXIT_GC_UNSAFE;
|
||||
}
|
||||
|
|
|
@ -214,6 +214,7 @@ MonoMethod * xamarin_bridge_get_mono_method (MonoReflectionMethod *method);
|
|||
void xamarin_bridge_free_mono_signature (MonoMethodSignature **signature);
|
||||
bool xamarin_register_monoassembly (MonoAssembly *assembly, GCHandle *exception_gchandle);
|
||||
void xamarin_install_nsautoreleasepool_hooks ();
|
||||
void xamarin_enable_new_refcount ();
|
||||
|
||||
MonoObject * xamarin_new_nsobject (id self, MonoClass *klass, GCHandle *exception_gchandle);
|
||||
bool xamarin_has_managed_ref (id self);
|
||||
|
@ -286,6 +287,10 @@ MonoObject * xamarin_gchandle_get_target (GCHandle handle);
|
|||
void xamarin_gchandle_free (GCHandle handle);
|
||||
MonoObject * xamarin_gchandle_unwrap (GCHandle handle); // Will get the target and free the GCHandle
|
||||
|
||||
typedef id (*xamarin_get_handle_func) (MonoObject *info);
|
||||
MonoToggleRefStatus xamarin_gc_toggleref_callback (uint8_t flags, id handle, xamarin_get_handle_func get_handle, MonoObject *info);
|
||||
void xamarin_gc_event (MonoGCEvent event);
|
||||
|
||||
/*
|
||||
* In MonoVM MonoObjects are tracked in memory/the stack directly by the GC, but that doesn't
|
||||
* work for CoreCLR, so we make it ref-counted. All code must use the functions below to retain/release
|
||||
|
|
Загрузка…
Ссылка в новой задаче