[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:
Rolf Bjarne Kvinge 2021-05-20 07:35:23 +02:00 коммит произвёл GitHub
Родитель ee5e2f0b09
Коммит f38187f054
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 89 добавлений и 57 удалений

Просмотреть файл

@ -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