From 655f2f921fb9d009aae5afeb50a2321cd9236e1c Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 30 Apr 2021 07:49:25 +0200 Subject: [PATCH] [runtime] Implement xamarin_get_reflection_method_method for CoreCLR. (#11383) --- runtime/coreclr-bridge.m | 16 ++++++++++------ runtime/mono-runtime.h.t4 | 9 ++++++++- runtime/monovm-bridge.m | 10 ++++++++++ runtime/runtime.m | 10 +--------- runtime/trampolines-invoke.m | 1 + runtime/trampolines.m | 8 +++++++- runtime/xamarin/runtime.h | 2 +- 7 files changed, 38 insertions(+), 18 deletions(-) diff --git a/runtime/coreclr-bridge.m b/runtime/coreclr-bridge.m index 0c2ef5cd7b..7487e52eb4 100644 --- a/runtime/coreclr-bridge.m +++ b/runtime/coreclr-bridge.m @@ -89,6 +89,16 @@ xamarin_bridge_register_product_assembly (GCHandle* exception_gchandle) xamarin_mono_object_release (&assembly); } +MonoMethod * +xamarin_bridge_get_mono_method (MonoReflectionMethod *method) +{ + // MonoMethod and MonoReflectionMethod are identical in CoreCLR (both are actually MonoObjects). + // However, we're returning a retained object, so we need to retain here. + xamarin_mono_object_retain (method); + LOG_CORECLR (stderr, "%s (%p): rv: %p\n", __func__, method, method); + return method; +} + MonoClass * xamarin_get_nsnumber_class () { @@ -152,12 +162,6 @@ xamarin_mono_object_release (MonoObject **mobj_ref) *mobj_ref = NULL; } -void -xamarin_mono_object_release (MonoReflectionMethod **mobj) -{ - xamarin_mono_object_release ((MonoObject **) mobj); -} - void xamarin_mono_object_release (MonoReflectionType **mobj) { diff --git a/runtime/mono-runtime.h.t4 b/runtime/mono-runtime.h.t4 index 2cc09ae0f5..754c2c1ea8 100644 --- a/runtime/mono-runtime.h.t4 +++ b/runtime/mono-runtime.h.t4 @@ -84,7 +84,12 @@ typedef enum { /* metadata/metadata.h */ typedef struct _MonoClass MonoClass; typedef struct _MonoDomain MonoDomain; +#if defined (CORECLR_RUNTIME) +// In Mono, MonoMethod is not related to MonoObject at all, but for the CoreCLR bridge we use the same struct representation for both types. +typedef struct _MonoObject MonoMethod; +#else typedef struct _MonoMethod MonoMethod; +#endif typedef struct _MonoMethodSignature MonoMethodSignature; typedef struct _MonoType MonoType; @@ -96,12 +101,14 @@ typedef struct _MonoClassField MonoClassField; /* metadata/object.h */ typedef struct _MonoString MonoString; typedef struct _MonoArray MonoArray; -typedef struct _MonoReflectionMethod MonoReflectionMethod; #if defined (CORECLR_RUNTIME) // In Mono, MonoReflectionAssembly is a substruct of MonoObject, but for the CoreCLR bridge we use the same struct representation for both types. typedef struct _MonoObject MonoReflectionAssembly; +// Same for MonoReflectionMethod +typedef struct _MonoObject MonoReflectionMethod; #else typedef struct _MonoReflectionAssembly MonoReflectionAssembly; +typedef struct _MonoReflectionMethod MonoReflectionMethod; #endif typedef struct _MonoReflectionType MonoReflectionType; typedef struct _MonoException MonoException; diff --git a/runtime/monovm-bridge.m b/runtime/monovm-bridge.m index cd903f9a86..7fadde9cdd 100644 --- a/runtime/monovm-bridge.m +++ b/runtime/monovm-bridge.m @@ -146,6 +146,16 @@ xamarin_bridge_register_product_assembly (GCHandle* exception_gchandle) xamarin_mono_object_release (&entry_assembly); } +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; +} + MonoClass * xamarin_get_inativeobject_class () { diff --git a/runtime/runtime.m b/runtime/runtime.m index 1c89cb854d..c9120d3bcd 100644 --- a/runtime/runtime.m +++ b/runtime/runtime.m @@ -646,15 +646,7 @@ xamarin_create_exception (const char *msg) MonoMethod * xamarin_get_reflection_method_method (MonoReflectionMethod *method) { - // COOP: Reads managed memory, needs to be in UNSAFE mode - MONO_ASSERT_GC_UNSAFE; - -#if defined (CORECLR_RUNTIME) - xamarin_assertion_message ("The method %s is not implemented yet for CoreCLR", __func__); -#else - PublicMonoReflectionMethod *rm = (PublicMonoReflectionMethod *) method; - return rm->method; -#endif + return xamarin_bridge_get_mono_method (method); } id diff --git a/runtime/trampolines-invoke.m b/runtime/trampolines-invoke.m index f4e91f5fab..1f0e77b968 100644 --- a/runtime/trampolines-invoke.m +++ b/runtime/trampolines-invoke.m @@ -179,6 +179,7 @@ xamarin_invoke_trampoline (enum TrampolineType type, id self, SEL sel, iterator_ reflection_method = (MonoReflectionMethod *) xamarin_gchandle_get_target (desc->method_handle); ADD_TO_MONOOBJECT_RELEASE_LIST (reflection_method); method = xamarin_get_reflection_method_method (reflection_method); + ADD_TO_MONOOBJECT_RELEASE_LIST (method); msig = mono_method_signature (method); semantic = desc->semantic & ArgumentSemanticMask; isCategoryInstance = (desc->semantic & ArgumentSemanticCategoryInstance) == ArgumentSemanticCategoryInstance; diff --git a/runtime/trampolines.m b/runtime/trampolines.m index 6ab89ad331..cf8d529fec 100644 --- a/runtime/trampolines.m +++ b/runtime/trampolines.m @@ -1493,6 +1493,8 @@ xamarin_smart_enum_to_nsstring (MonoObject *value, void *context /* token ref */ retval = mono_runtime_invoke (managed_method, NULL, arg_ptrs, &exception); + xamarin_mono_object_release (&managed_method); + if (exception) { *exception_gchandle = xamarin_gchandle_new (exception, FALSE); return NULL; @@ -1530,13 +1532,17 @@ xamarin_nsstring_to_smart_enum (id value, void *ptr, MonoClass *managedType, voi if (*exception_gchandle != INVALID_GCHANDLE) return NULL; arg0 = xamarin_get_nsobject_with_type_for_ptr (value, false, xamarin_get_parameter_type (managed_method, 0), exception_gchandle); - if (*exception_gchandle != INVALID_GCHANDLE) return NULL; + if (*exception_gchandle != INVALID_GCHANDLE) { + xamarin_mono_object_release (&managed_method); + return NULL; + } arg_ptrs [0] = arg0; obj = mono_runtime_invoke (managed_method, NULL, arg_ptrs, &exception); xamarin_mono_object_release (&arg0); + xamarin_mono_object_release (&managed_method); if (exception) { *exception_gchandle = xamarin_gchandle_new (exception, FALSE); diff --git a/runtime/xamarin/runtime.h b/runtime/xamarin/runtime.h index 2b69c81431..446b999b96 100644 --- a/runtime/xamarin/runtime.h +++ b/runtime/xamarin/runtime.h @@ -208,6 +208,7 @@ bool xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKey void* xamarin_pinvoke_override (const char *libraryName, const char *entrypointName); void xamarin_bridge_call_runtime_initialize (struct InitializationOptions* options, GCHandle* exception_gchandle); void xamarin_bridge_register_product_assembly (GCHandle* exception_gchandle); +MonoMethod * xamarin_bridge_get_mono_method (MonoReflectionMethod *method); bool xamarin_register_monoassembly (MonoAssembly *assembly, GCHandle *exception_gchandle); void xamarin_install_nsautoreleasepool_hooks (); @@ -291,7 +292,6 @@ MonoObject * xamarin_gchandle_unwrap (GCHandle handle); // Will get the target a void xamarin_mono_object_retain (MonoObject *mobj); // Use C++ linking to be able to use method overloading, so that callers don't have to cast their variables to 'MonoObject**' (which improves type safety a lot). extern "C++" void xamarin_mono_object_release (MonoObject **mobj); -extern "C++" void xamarin_mono_object_release (MonoReflectionMethod **mobj); extern "C++" void xamarin_mono_object_release (MonoReflectionType **mobj); extern "C++" void xamarin_mono_object_release (MonoString **mobj); #else