diff --git a/runtime/delegates.t4 b/runtime/delegates.t4 index 1a035e258d..54872267a8 100644 --- a/runtime/delegates.t4 +++ b/runtime/delegates.t4 @@ -50,16 +50,18 @@ OnlyDynamicUsage = false, }, - new XDelegate ("MonoObject *", "IntPtr", "xamarin_get_block_wrapper_creator", - "MonoObject *", "IntPtr", "method", + new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_block_wrapper_creator", + "GCHandle->MonoReflectionMethod *", "IntPtr", "method", "int", "int", "parameter" ) { WrappedManagedFunction = "GetBlockWrapperCreator", OnlyDynamicUsage = true, }, - new XDelegate ("MonoObject *", "IntPtr", "xamarin_create_block_proxy", - "MonoObject *", "IntPtr", "method", + new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_create_block_proxy", + // Don't convert the 'method' parameter, we already have a GCHandle + // available we can use. + "GCHandle", "IntPtr", "method", "void *", "IntPtr", "block" ) { WrappedManagedFunction = "CreateBlockProxy", @@ -145,15 +147,17 @@ OnlyDynamicUsage = false, }, - new XDelegate ("MonoReflectionMethod *", "IntPtr", "xamarin_get_method_from_token", + // Do not automatically unwrap the return value, because otherwise we might need to immediately wrap it in a GCHandle again. + new XDelegate ("GCHandle", "IntPtr", "xamarin_get_method_from_token", "unsigned int", "uint", "token_ref" ) { WrappedManagedFunction = "GetMethodFromToken", OnlyDynamicUsage = false, }, - new XDelegate ("MonoReflectionMethod *", "IntPtr", "xamarin_get_generic_method_from_token", - "MonoObject *", "IntPtr", "obj", + // Do not automatically unwrap the return value, because otherwise we might need to immediately wrap it in a GCHandle again. + new XDelegate ("GCHandle", "IntPtr", "xamarin_get_generic_method_from_token", + "GCHandle->MonoObject *", "IntPtr", "obj_handle", "unsigned int", "uint", "token_ref" ) { WrappedManagedFunction = "GetGenericMethodFromToken", diff --git a/runtime/runtime.m b/runtime/runtime.m index 952da38ab9..5b961958a0 100644 --- a/runtime/runtime.m +++ b/runtime/runtime.m @@ -2074,7 +2074,7 @@ static MonoReferenceQueue *block_wrapper_queue; * that can be used to create a new delegate, this returns the method that can * create the method */ -static MonoObject * +static GCHandle get_method_block_wrapper_creator (MonoMethod *method, int par, guint32 *exception_gchandle) { // COOP: accesses managed memory: unsafe mode. @@ -2098,12 +2098,12 @@ get_method_block_wrapper_creator (MonoMethod *method, int par, guint32 *exceptio pthread_mutex_unlock (&wrapper_hash_lock); if (res != NULL){ // PRINT ("Found match: %x", (int) res); - return res; + return xamarin_gchandle_new (res, false); } - res = xamarin_get_block_wrapper_creator ((MonoObject *) mono_method_get_object (mono_domain_get (), method, NULL), (int) par, exception_gchandle); + res = xamarin_get_block_wrapper_creator (mono_method_get_object (mono_domain_get (), method, NULL), (int) par, exception_gchandle); if (*exception_gchandle != 0) - return NULL; + return INVALID_GCHANDLE; // PRINT ("New value: %x", (int) res); nmp = (MethodAndPar *) malloc (sizeof (MethodAndPar)); @@ -2114,7 +2114,7 @@ get_method_block_wrapper_creator (MonoMethod *method, int par, guint32 *exceptio MONO_EXIT_GC_SAFE; mono_g_hash_table_insert (xamarin_wrapper_hash, nmp, res); pthread_mutex_unlock (&wrapper_hash_lock); - return res; + return xamarin_gchandle_new (res, false); } void @@ -2149,15 +2149,15 @@ xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref, MONO_ASSERT_GC_UNSAFE; MonoObject *delegate = NULL; + GCHandle obj_handle = INVALID_GCHANDLE; if (nativeBlock == NULL) return NULL; - MonoObject *obj; if (token_ref != INVALID_TOKEN_REF) { - obj = (MonoObject *) xamarin_get_method_from_token (token_ref, exception_gchandle); + obj_handle = xamarin_get_method_from_token (token_ref, exception_gchandle); } else { - obj = get_method_block_wrapper_creator (method, par, exception_gchandle); + obj_handle = get_method_block_wrapper_creator (method, par, exception_gchandle); } if (*exception_gchandle != 0) goto cleanup; @@ -2165,7 +2165,7 @@ xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref, /* retain or copy (if it's a stack block) the block */ nativeBlock = _Block_copy (nativeBlock); - delegate = xamarin_create_block_proxy (obj, nativeBlock, exception_gchandle); + delegate = xamarin_create_block_proxy (obj_handle, nativeBlock, exception_gchandle); if (*exception_gchandle != 0) { _Block_release (nativeBlock); delegate = NULL; @@ -2183,6 +2183,7 @@ xamarin_get_delegate_for_block_parameter (MonoMethod *method, guint32 token_ref, pthread_mutex_unlock (&wrapper_hash_lock); cleanup: + xamarin_gchandle_free (obj_handle); return delegate; } @@ -2662,7 +2663,7 @@ xamarin_get_managed_method_for_token (guint32 token_ref, guint32 *exception_gcha { MonoReflectionMethod *reflection_method; - reflection_method = xamarin_get_method_from_token (token_ref, exception_gchandle); + reflection_method = (MonoReflectionMethod *) xamarin_gchandle_unwrap (xamarin_get_method_from_token (token_ref, exception_gchandle)); if (*exception_gchandle != 0) return NULL; return xamarin_get_reflection_method_method (reflection_method); diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index 0bfa38c6dc..ef2125e9bd 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -454,12 +454,12 @@ namespace ObjCRuntime { static IntPtr GetBlockWrapperCreator (IntPtr method, int parameter) { - return ObjectWrapper.Convert (GetBlockWrapperCreator ((MethodInfo) ObjectWrapper.Convert (method), parameter)); + return AllocGCHandle (GetBlockWrapperCreator ((MethodInfo) GetGCHandleTarget (method), parameter)); } static IntPtr CreateBlockProxy (IntPtr method, IntPtr block) { - return ObjectWrapper.Convert (CreateBlockProxy ((MethodInfo) ObjectWrapper.Convert (method), block)); + return AllocGCHandle (CreateBlockProxy ((MethodInfo) GetGCHandleTarget (method), block)); } static IntPtr CreateDelegateProxy (IntPtr method, IntPtr @delegate, IntPtr signature, uint token_ref) @@ -661,7 +661,7 @@ namespace ObjCRuntime { { var method = Class.ResolveMethodTokenReference (token_ref); if (method != null) - return ObjectWrapper.Convert (method); + return AllocGCHandle (method); return IntPtr.Zero; } @@ -672,11 +672,11 @@ namespace ObjCRuntime { if (method == null) return IntPtr.Zero; - var nsobj = ObjectWrapper.Convert (obj) as NSObject; + var nsobj = GetGCHandleTarget (obj) as NSObject; if (nsobj == null) throw ErrorHelper.CreateError (8023, $"An instance object is required to construct a closed generic method for the open generic method: {method.DeclaringType.FullName}.{method.Name} (token reference: 0x{token_ref:X}). Please file a bug report at https://github.com/xamarin/xamarin-macios/issues/new."); - return ObjectWrapper.Convert (FindClosedMethod (nsobj.GetType (), method)); + return AllocGCHandle (FindClosedMethod (nsobj.GetType (), method)); } static IntPtr TryGetOrConstructNSObjectWrapped (IntPtr ptr) diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index 2dee89c368..ad9ec3dba0 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -3906,7 +3906,7 @@ namespace Registrar { // no locking should be required here, it doesn't matter if we overwrite the field (it'll be the same value). body.WriteLine ("if (!managed_method) {"); - body.Write ("MonoReflectionMethod *reflection_method = "); + body.Write ("GCHandle reflection_method_handle = "); if (isGeneric) body.Write ("xamarin_get_generic_method_from_token (mthis, "); else @@ -3917,6 +3917,8 @@ namespace Registrar { } else { body.WriteLine ("0x{0:X}, &exception_gchandle);", token_ref); } + body.Write ("MonoReflectionMethod *reflection_method = (MonoReflectionMethod *) xamarin_gchandle_unwrap (reflection_method_handle);"); + body.WriteLine ("if (exception_gchandle != 0) goto exception_handling;"); body.WriteLine ("managed_method = xamarin_get_reflection_method_method (reflection_method);"); if (merge_bodies)