From 234bd6e052c7143ebb937f5bafc70ceec16a0576 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 10 Nov 2022 11:57:36 +0100 Subject: [PATCH 1/3] [perf] [runtime] Optimize startup by using function pointers instead of delegates for our native->managed bridge. --- runtime/Delegates.cs.t4 | 33 +++++++++++++++++++-------------- runtime/delegates.t4 | 26 ++++++++++++++++++++++---- src/ObjCRuntime/Runtime.cs | 13 +++++++++---- 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/runtime/Delegates.cs.t4 b/runtime/Delegates.cs.t4 index 6bb0ed6236fd..bfb18863c394 100644 --- a/runtime/Delegates.cs.t4 +++ b/runtime/Delegates.cs.t4 @@ -25,17 +25,11 @@ using Registrar; namespace ObjCRuntime { public unsafe partial class Runtime { +#if !NET <# foreach (var d in delegates) { #> -<# - if (d.OnlyCoreCLR) - Write ("#if NET\n"); -#> internal delegate <#= d.ReturnType.MType #> <#= d.SimpleEntryPoint #>_delegate (<#= d.MArgumentSignature #>); -<# - if (d.OnlyCoreCLR) - Write ("#endif // NET\n"); -#> <# } #> +#endif // !NET internal struct Delegates { <# foreach (var d in delegates) { #> @@ -56,11 +50,15 @@ namespace ObjCRuntime { if (d.OnlyCoreCLR) Write ("#if NET\n"); #> +#if NET + [UnmanagedCallersOnly] +#else [MonoPInvokeCallback (typeof (<#= d.SimpleEntryPoint #>_delegate))] - static <#= d.ReturnType.MType #> <#= d.SimpleEntryPoint #> (<#= d.MArgumentSignature #>) +#endif + static unsafe <#= d.ReturnType.MType #> <#= d.SimpleEntryPoint #> (<#= d.MArgumentSignature #>) <# if (d.ExceptionHandling) { #> { - exception_gchandle = IntPtr.Zero; + *exception_gchandle = IntPtr.Zero; try { <# if (string.IsNullOrEmpty (d.WrappedManagedFunction)) { #> throw new NotImplementedException (); @@ -69,8 +67,8 @@ namespace ObjCRuntime { <# } #> } catch (Exception ex) { var handle = GCHandle.Alloc (ex, GCHandleType.Normal); - exception_gchandle = GCHandle.ToIntPtr (handle); -<# if (d.SimpleEntryPoint == "get_nsobject_with_type") { #> created = false; + *exception_gchandle = GCHandle.ToIntPtr (handle); +<# if (d.SimpleEntryPoint == "get_nsobject_with_type") { #> *created = false; <# } #> <# if (d.ReturnType.MType != "void") { #> return default (<#= d.ReturnType.MType #>); <# } #> @@ -93,7 +91,7 @@ namespace ObjCRuntime { <# } #> [BindingImpl (BindingImplOptions.Optimizable)] // To inline the Runtime.DynamicRegistrationSupported code if possible. - static void RegisterDelegates (InitializationOptions* options) + unsafe static void RegisterDelegates (InitializationOptions* options) { <# foreach (var d in delegates) { if (d.OnlyDynamicUsage) continue; #> @@ -102,8 +100,11 @@ namespace ObjCRuntime { Write ("#if NET\n"); Write ("\t\t\tif (IsCoreCLR)\n\t"); } -#> +#>#if NET + options->Delegates-><#= d.SimpleEntryPoint #> = (IntPtr) (void *) <#= d.UnmanagedDelegateCast #> &<#= d.SimpleEntryPoint #>; +#else options->Delegates-><#= d.SimpleEntryPoint #> = GetFunctionPointer (new <#= d.SimpleEntryPoint #>_delegate (<#= d.SimpleEntryPoint #>)); +#endif <# if (d.OnlyCoreCLR) Write ("#endif // NET\n"); @@ -125,7 +126,11 @@ namespace ObjCRuntime { Write ("\t\t\tif (IsCoreCLR)\n\t"); } #> +#if NET + options->Delegates-><#= d.SimpleEntryPoint #> = (IntPtr) (void *) <#= d.UnmanagedDelegateCast #> &<#= d.SimpleEntryPoint #>; +#else options->Delegates-><#= d.SimpleEntryPoint #> = GetFunctionPointer (new <#= d.SimpleEntryPoint #>_delegate (<#= d.SimpleEntryPoint #>)); +#endif <# if (d.OnlyCoreCLR) Write ("#endif // NET\n"); diff --git a/runtime/delegates.t4 b/runtime/delegates.t4 index fb31092535f0..708455d2d9d0 100644 --- a/runtime/delegates.t4 +++ b/runtime/delegates.t4 @@ -193,7 +193,7 @@ new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_nsobject_with_type", "id", "IntPtr", "obj", "GCHandle->MonoReflectionType *", "IntPtr", "type", - "int32_t *", "out bool", "created" + "int32_t *", "bool*", "created" ) { WrappedManagedFunction = "GetNSObjectWithType", OnlyDynamicUsage = false, @@ -227,7 +227,7 @@ "SEL", "IntPtr", "sel", "bool", "bool", "is_static", "id", "IntPtr", "obj", - "GCHandle *", "ref IntPtr", "mthis", + "GCHandle *", "IntPtr*", "mthis", "MethodDescription *", "IntPtr", "desc" ) { WrappedManagedFunction = "GetMethodAndObjectForSelector", @@ -237,7 +237,7 @@ new XDelegate ("GCHandle", "IntPtr", "xamarin_create_product_exception_for_error", "int", "int", "code", "GCHandle", "IntPtr", "inner_exception_gchandle", - "const char *", "string", "message" + "const char *", "IntPtr", "message" ) { WrappedManagedFunction = "CreateProductException", OnlyDynamicUsage = false, @@ -878,6 +878,24 @@ } } + public string UnmanagedDelegateCast { + get { + var builder = new StringBuilder (); + builder.Append ("(delegate* unmanaged<"); + + foreach (var arg in Arguments) { + builder.Append (arg.MType); + builder.Append (", "); + } + if (ExceptionHandling) + builder.Append ("IntPtr*, "); + builder.Append (ReturnType.MType); + + builder.Append (">)"); + return builder.ToString (); + } + } + public string AlignEntryPoint { get { return new string (' ', Delegates.MaxEntryPointLength - EntryPoint.Length); @@ -949,7 +967,7 @@ } else { if (Arguments.Count > 0) builder.Append (", "); - builder.Append ("out IntPtr exception_gchandle"); + builder.Append ("IntPtr* exception_gchandle"); } } diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index 84d06b79d7db..b8605acdde77 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -791,10 +791,12 @@ static IntPtr GetINativeObject_Static (IntPtr ptr, bool owns, uint iface_token, return AllocGCHandle (GetINativeObject (ptr, owns, iface, type)); } - static IntPtr GetNSObjectWithType (IntPtr ptr, IntPtr type_ptr, out bool created) + unsafe static IntPtr GetNSObjectWithType (IntPtr ptr, IntPtr type_ptr, bool* createdPtr) { var type = (System.Type) GetGCHandleTarget (type_ptr)!; - return AllocGCHandle (GetNSObject (ptr, type, MissingCtorResolution.ThrowConstructor1NotFound, true, true, out created)); + var rv = AllocGCHandle (GetNSObject (ptr, type, MissingCtorResolution.ThrowConstructor1NotFound, true, true, out var created)); + *createdPtr = created; + return rv; } static void Dispose (IntPtr gchandle) @@ -826,13 +828,15 @@ static bool IsParameterOut (IntPtr info, int parameter) return parameters [parameter].IsOut; } - static void GetMethodAndObjectForSelector (IntPtr klass, IntPtr sel, bool is_static, IntPtr obj, ref IntPtr mthis, IntPtr desc) + unsafe static void GetMethodAndObjectForSelector (IntPtr klass, IntPtr sel, bool is_static, IntPtr obj, IntPtr* mthisPtr, IntPtr desc) { + IntPtr mthis = *mthisPtr; Registrar.GetMethodDescriptionAndObject (Class.Lookup (klass), sel, is_static, obj, ref mthis, desc); + *mthisPtr = mthis; } // If inner_exception_gchandle is provided, it will be freed. - static IntPtr CreateProductException (int code, IntPtr inner_exception_gchandle, string msg) + static IntPtr CreateProductException (int code, IntPtr inner_exception_gchandle, IntPtr utf8Message) { Exception? inner_exception = null; if (inner_exception_gchandle != IntPtr.Zero) { @@ -840,6 +844,7 @@ static IntPtr CreateProductException (int code, IntPtr inner_exception_gchandle, inner_exception = (Exception?) gchandle.Target; gchandle.Free (); } + var msg = Marshal.PtrToStringAuto (utf8Message)!; Exception ex = ErrorHelper.CreateError (code, inner_exception, msg); return AllocGCHandle (ex); } From 22cc77ff68d64421f7243b6678ce28c3fcffce33 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 10 Nov 2022 13:46:14 +0100 Subject: [PATCH 2/3] Fix legacy mode. --- runtime/Delegates.cs.t4 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runtime/Delegates.cs.t4 b/runtime/Delegates.cs.t4 index bfb18863c394..79cb329fe455 100644 --- a/runtime/Delegates.cs.t4 +++ b/runtime/Delegates.cs.t4 @@ -27,6 +27,10 @@ namespace ObjCRuntime { #if !NET <# foreach (var d in delegates) { #> +<# + if (d.OnlyCoreCLR) + continue; +#> internal delegate <#= d.ReturnType.MType #> <#= d.SimpleEntryPoint #>_delegate (<#= d.MArgumentSignature #>); <# } #> #endif // !NET From 5b5da77c3bdb55f6f45ca88e2f5de5382f04c427 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 11 Nov 2022 08:05:02 +0100 Subject: [PATCH 3/3] Don't use 'bool' in signatures, it's not blittable. --- runtime/Delegates.cs.t4 | 2 +- runtime/delegates.t4 | 36 +++++++++--------- src/ObjCRuntime/Runtime.CoreCLR.cs | 35 +++++++++-------- src/ObjCRuntime/Runtime.cs | 61 ++++++++++++++++-------------- 4 files changed, 72 insertions(+), 62 deletions(-) diff --git a/runtime/Delegates.cs.t4 b/runtime/Delegates.cs.t4 index 79cb329fe455..51da63acc46a 100644 --- a/runtime/Delegates.cs.t4 +++ b/runtime/Delegates.cs.t4 @@ -72,7 +72,7 @@ namespace ObjCRuntime { } catch (Exception ex) { var handle = GCHandle.Alloc (ex, GCHandleType.Normal); *exception_gchandle = GCHandle.ToIntPtr (handle); -<# if (d.SimpleEntryPoint == "get_nsobject_with_type") { #> *created = false; +<# if (d.SimpleEntryPoint == "get_nsobject_with_type") { #> *created = 0; <# } #> <# if (d.ReturnType.MType != "void") { #> return default (<#= d.ReturnType.MType #>); <# } #> diff --git a/runtime/delegates.t4 b/runtime/delegates.t4 index 708455d2d9d0..478ebab13a8b 100644 --- a/runtime/delegates.t4 +++ b/runtime/delegates.t4 @@ -115,14 +115,14 @@ new XDelegate ("void", "void", "xamarin_get_method_for_selector", "Class", "IntPtr", "cls", "SEL", "IntPtr", "sel", - "bool", "bool", "is_static", + "int8_t", "sbyte", "is_static", "MethodDescription *", "IntPtr", "desc" ) { WrappedManagedFunction = "GetMethodForSelector", OnlyDynamicUsage = true, }, - new XDelegate ("bool", "bool", "xamarin_has_nsobject", + new XDelegate ("int8_t", "sbyte", "xamarin_has_nsobject", "id", "IntPtr", "obj" ) { WrappedManagedFunction = "HasNSObject", @@ -156,7 +156,7 @@ new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_inative_object_dynamic", "id", "IntPtr", "obj", - "bool", "bool", "owns", + "int8_t", "sbyte", "owns", "GCHandle->MonoReflectionType *", "IntPtr", "type" ) { WrappedManagedFunction = "GetINativeObject_Dynamic", @@ -182,7 +182,7 @@ new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_inative_object_static", "id", "IntPtr", "obj", - "bool", "bool", "owns", + "int8_t", "sbyte", "owns", "unsigned int", "uint", "iface_token_ref", "unsigned int", "uint", "implementation_token_ref" ) { @@ -193,7 +193,7 @@ new XDelegate ("GCHandle->MonoObject *", "IntPtr", "xamarin_get_nsobject_with_type", "id", "IntPtr", "obj", "GCHandle->MonoReflectionType *", "IntPtr", "type", - "int32_t *", "bool*", "created" + "int32_t *", "int*", "created" ) { WrappedManagedFunction = "GetNSObjectWithType", OnlyDynamicUsage = false, @@ -206,7 +206,7 @@ OnlyDynamicUsage = false, }, - new XDelegate ("bool", "bool", "xamarin_is_parameter_transient", + new XDelegate ("int8_t", "sbyte", "xamarin_is_parameter_transient", "GCHandle->MonoReflectionMethod *", "IntPtr", "method", "int", "int", "parameter" ) { @@ -214,7 +214,7 @@ OnlyDynamicUsage = true, }, - new XDelegate ("bool", "bool", "xamarin_is_parameter_out", + new XDelegate ("int8_t", "sbyte", "xamarin_is_parameter_out", "GCHandle->MonoReflectionMethod *", "IntPtr", "method", "int", "int", "parameter" ) { @@ -225,7 +225,7 @@ new XDelegate ("void", "void", "xamarin_get_method_and_object_for_selector", "Class", "IntPtr", "cls", "SEL", "IntPtr", "sel", - "bool", "bool", "is_static", + "int8_t", "sbyte", "is_static", "id", "IntPtr", "obj", "GCHandle *", "IntPtr*", "mthis", "MethodDescription *", "IntPtr", "desc" @@ -266,7 +266,7 @@ new XDelegate ("enum MarshalObjectiveCExceptionMode", "MarshalObjectiveCExceptionMode", "xamarin_on_marshal_objectivec_exception", "id", "IntPtr", "exception", - "bool", "bool", "throwManagedAsDefault" + "int8_t", "sbyte", "throwManagedAsDefault" ) { WrappedManagedFunction = "OnMarshalObjectiveCException", OnlyDynamicUsage = false, @@ -494,7 +494,7 @@ OnlyCoreCLR = true, }, - new XDelegate ("bool", "bool", "xamarin_bridge_isinstance", + new XDelegate ("int8_t", "sbyte", "xamarin_bridge_isinstance", "GCHandle", "IntPtr", "gchandle", "GCHandle", "IntPtr", "type" ) { @@ -529,7 +529,7 @@ OnlyCoreCLR = true, }, - new XDelegate ("bool", "bool", "xamarin_bridge_is_enum", + new XDelegate ("int8_t", "sbyte", "xamarin_bridge_is_enum", "MonoObject *", "MonoObject *", "typeobj" ) { WrappedManagedFunction = "IsEnum", @@ -545,7 +545,7 @@ OnlyCoreCLR = true, }, - new XDelegate ("bool", "bool", "xamarin_bridge_is_byref", + new XDelegate ("int8_t", "sbyte", "xamarin_bridge_is_byref", "MonoObject *", "MonoObject *", "typeobj" ) { WrappedManagedFunction = "IsByRef", @@ -553,7 +553,7 @@ OnlyCoreCLR = true, }, - new XDelegate ("bool", "bool", "xamarin_bridge_is_valuetype", + new XDelegate ("int8_t", "sbyte", "xamarin_bridge_is_valuetype", "MonoObject *", "MonoObject *", "typeobj" ) { WrappedManagedFunction = "IsValueType", @@ -561,7 +561,7 @@ OnlyCoreCLR = true, }, - new XDelegate ("bool", "bool", "xamarin_bridge_is_nullable", + new XDelegate ("int8_t", "sbyte", "xamarin_bridge_is_nullable", "MonoObject *", "MonoObject *", "typeobj" ) { WrappedManagedFunction = "IsNullable", @@ -585,7 +585,7 @@ OnlyCoreCLR = true, }, - new XDelegate ("bool", "bool", "xamarin_bridge_is_delegate", + new XDelegate ("int8_t", "sbyte", "xamarin_bridge_is_delegate", "MonoObject *", "MonoObject *", "typeobj" ) { WrappedManagedFunction = "IsDelegate", @@ -593,7 +593,7 @@ OnlyCoreCLR = true, }, - new XDelegate ("bool", "bool", "xamarin_bridge_is_class_of_type", + new XDelegate ("int8_t", "sbyte", "xamarin_bridge_is_class_of_type", "MonoObject *", "MonoObject *", "classobj", "enum XamarinLookupTypes", "Runtime.TypeLookup", "type" ) { @@ -672,14 +672,14 @@ OnlyDynamicUsage = false, }, - new XDelegate ("bool", "bool", "xamarin_attempt_retain_nsobject", + new XDelegate ("int8_t", "sbyte", "xamarin_attempt_retain_nsobject", "GCHandle->MonoObject *", "IntPtr", "obj" ) { WrappedManagedFunction = "AttemptRetainNSObject", OnlyDynamicUsage = false, }, - new XDelegate ("bool", "bool", "xamarin_invoke_conforms_to_protocol", + new XDelegate ("int8_t", "sbyte", "xamarin_invoke_conforms_to_protocol", "id", "IntPtr", "obj", "Protocol *", "IntPtr", "protocol" ) { diff --git a/src/ObjCRuntime/Runtime.CoreCLR.cs b/src/ObjCRuntime/Runtime.CoreCLR.cs index 8d691b525f00..d59d18a3c706 100644 --- a/src/ObjCRuntime/Runtime.CoreCLR.cs +++ b/src/ObjCRuntime/Runtime.CoreCLR.cs @@ -248,9 +248,10 @@ static unsafe void SetPendingException (MonoObject* exception_obj) ObjectiveCMarshal.SetMessageSendPendingException (exc); } - unsafe static bool IsClassOfType (MonoObject *typeobj, TypeLookup match) + unsafe static sbyte IsClassOfType (MonoObject *typeobj, TypeLookup match) { - return IsClassOfType ((Type) GetMonoObjectTarget (typeobj), match); + var rv = IsClassOfType ((Type) GetMonoObjectTarget (typeobj), match); + return (sbyte) (rv ? 1 : 0); } static bool IsClassOfType (Type type, TypeLookup match) @@ -499,26 +500,26 @@ static IntPtr ObjectGetType (MonoObjectPtr mobj) return GetMonoObject (obj.GetType ()); } - unsafe static bool IsDelegate (MonoObject* typeobj) + unsafe static sbyte IsDelegate (MonoObject* typeobj) { var type = (Type) GetMonoObjectTarget (typeobj); var rv = typeof (MulticastDelegate).IsAssignableFrom (type); log_coreclr ($"IsDelegate ({type.FullName}) => {rv}"); - return rv; + return (sbyte) (rv ? 1 : 0); } - static bool IsInstance (MonoObjectPtr mobj, MonoObjectPtr mtype) + static sbyte IsInstance (MonoObjectPtr mobj, MonoObjectPtr mtype) { var obj = GetMonoObjectTarget (mobj); if (obj == null) - return false; + return 0; var type = (Type) GetMonoObjectTarget (mtype); var rv = type.IsAssignableFrom (obj.GetType ()); log_coreclr ($"IsInstance ({obj.GetType ()}, {type})"); - return rv; + return (sbyte) (rv ? 1 : 0); } static unsafe IntPtr GetMethodSignature (MonoObject* methodobj) @@ -837,9 +838,10 @@ static object Box (Type type, IntPtr value) return boxed; } - static unsafe bool IsNullable (MonoObject* type) + static unsafe sbyte IsNullable (MonoObject* type) { - return IsNullable ((Type) GetMonoObjectTarget (type)); + var rv = IsNullable ((Type) GetMonoObjectTarget (type)); + return (sbyte) (rv ? 1 : 0); } static bool IsNullable (Type type) @@ -853,22 +855,25 @@ static bool IsNullable (Type type) return false; } - unsafe static bool IsByRef (MonoObject *typeobj) + unsafe static sbyte IsByRef (MonoObject *typeobj) { var type = (Type) GetMonoObjectTarget (typeobj); - return type.IsByRef; + var rv = type.IsByRef; + return (sbyte) (rv ? 1 : 0); } - unsafe static bool IsValueType (MonoObject *typeobj) + unsafe static sbyte IsValueType (MonoObject *typeobj) { var type = (Type) GetMonoObjectTarget (typeobj); - return type.IsValueType; + var rv = type.IsValueType; + return (sbyte) (rv ? 1 : 0); } - unsafe static bool IsEnum (MonoObject *typeobj) + unsafe static sbyte IsEnum (MonoObject *typeobj) { var type = (Type) GetMonoObjectTarget (typeobj); - return type.IsEnum; + var rv = type.IsEnum; + return (sbyte) (rv ? 1 : 0); } static unsafe MonoObject* GetEnumBaseType (MonoObject* typeobj) diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index b8605acdde77..6bcc889da84b 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -372,9 +372,9 @@ static bool OnAssemblyRegistration (AssemblyName assembly_name) public static event MarshalObjectiveCExceptionHandler? MarshalObjectiveCException; public static event MarshalManagedExceptionHandler? MarshalManagedException; - static MarshalObjectiveCExceptionMode OnMarshalObjectiveCException (IntPtr exception_handle, bool throwManagedAsDefault) + static MarshalObjectiveCExceptionMode OnMarshalObjectiveCException (IntPtr exception_handle, sbyte throwManagedAsDefault) { - if (throwManagedAsDefault && MarshalObjectiveCException is null) + if (throwManagedAsDefault != 0 && MarshalObjectiveCException is null) return MarshalObjectiveCExceptionMode.ThrowManagedException; if (MarshalObjectiveCException is not null) { @@ -382,7 +382,7 @@ static MarshalObjectiveCExceptionMode OnMarshalObjectiveCException (IntPtr excep var args = new MarshalObjectiveCExceptionEventArgs () { Exception = exception, - ExceptionMode = throwManagedAsDefault ? MarshalObjectiveCExceptionMode.ThrowManagedException : objc_exception_mode, + ExceptionMode = (throwManagedAsDefault != 0) ? MarshalObjectiveCExceptionMode.ThrowManagedException : objc_exception_mode, }; MarshalObjectiveCException (null, args); @@ -723,15 +723,16 @@ static IntPtr GetSelector (IntPtr sel) return AllocGCHandle (new Selector (sel)); } - static void GetMethodForSelector (IntPtr cls, IntPtr sel, bool is_static, IntPtr desc) + static void GetMethodForSelector (IntPtr cls, IntPtr sel, sbyte is_static, IntPtr desc) { // This is called by the old registrar code. - Registrar.GetMethodDescription (Class.Lookup (cls), sel, is_static, desc); + Registrar.GetMethodDescription (Class.Lookup (cls), sel, is_static != 0, desc); } - static bool HasNSObject (IntPtr ptr) + static sbyte HasNSObject (IntPtr ptr) { - return TryGetNSObject (ptr, evenInFinalizerQueue: false) is not null; + var rv = TryGetNSObject (ptr, evenInFinalizerQueue: false) is not null; + return (sbyte) (rv ? 1 : 0); } static IntPtr GetHandleForINativeObject (IntPtr ptr) @@ -771,16 +772,16 @@ static IntPtr TryGetOrConstructNSObjectWrapped (IntPtr ptr) return AllocGCHandle (GetNSObject (ptr, MissingCtorResolution.Ignore, true)); } - static IntPtr GetINativeObject_Dynamic (IntPtr ptr, bool owns, IntPtr type_ptr) + static IntPtr GetINativeObject_Dynamic (IntPtr ptr, sbyte owns, IntPtr type_ptr) { /* * This method is called from marshalling bridge (dynamic mode). */ var type = (System.Type) GetGCHandleTarget (type_ptr)!; - return AllocGCHandle (GetINativeObject (ptr, owns, type, null)); + return AllocGCHandle (GetINativeObject (ptr, owns != 0, type, null)); } - static IntPtr GetINativeObject_Static (IntPtr ptr, bool owns, uint iface_token, uint implementation_token) + static IntPtr GetINativeObject_Static (IntPtr ptr, sbyte owns, uint iface_token, uint implementation_token) { /* * This method is called from generated code from the static registrar. @@ -788,14 +789,14 @@ static IntPtr GetINativeObject_Static (IntPtr ptr, bool owns, uint iface_token, var iface = Class.ResolveTypeTokenReference (iface_token)!; var type = Class.ResolveTypeTokenReference (implementation_token); - return AllocGCHandle (GetINativeObject (ptr, owns, iface, type)); + return AllocGCHandle (GetINativeObject (ptr, owns != 0, iface, type)); } - unsafe static IntPtr GetNSObjectWithType (IntPtr ptr, IntPtr type_ptr, bool* createdPtr) + unsafe static IntPtr GetNSObjectWithType (IntPtr ptr, IntPtr type_ptr, int* createdPtr) { var type = (System.Type) GetGCHandleTarget (type_ptr)!; var rv = AllocGCHandle (GetNSObject (ptr, type, MissingCtorResolution.ThrowConstructor1NotFound, true, true, out var created)); - *createdPtr = created; + *createdPtr = created ? 1 : 0; return rv; } @@ -804,34 +805,36 @@ static void Dispose (IntPtr gchandle) ((IDisposable?) GetGCHandleTarget (gchandle))?.Dispose (); } - static bool IsParameterTransient (IntPtr info, int parameter) + static sbyte IsParameterTransient (IntPtr info, int parameter) { var minfo = GetGCHandleTarget (info) as MethodInfo; if (minfo is null) - return false; // might be a ConstructorInfo (bug #15583), but we don't care about that (yet at least). + return 0; // might be a ConstructorInfo (bug #15583), but we don't care about that (yet at least). minfo = minfo.GetBaseDefinition (); var parameters = minfo.GetParameters (); if (parameters.Length <= parameter) - return false; - return parameters [parameter].IsDefined (typeof(TransientAttribute), false); + return 0; + var rv = parameters [parameter].IsDefined (typeof(TransientAttribute), false); + return (sbyte) (rv ? 1 : 0); } - static bool IsParameterOut (IntPtr info, int parameter) + static sbyte IsParameterOut (IntPtr info, int parameter) { var minfo = GetGCHandleTarget (info) as MethodInfo; if (minfo is null) - return false; // might be a ConstructorInfo (bug #15583), but we don't care about that (yet at least). + return 0; // might be a ConstructorInfo (bug #15583), but we don't care about that (yet at least). minfo = minfo.GetBaseDefinition (); var parameters = minfo.GetParameters (); if (parameters.Length <= parameter) - return false; - return parameters [parameter].IsOut; + return 0; + var rv = parameters [parameter].IsOut; + return (sbyte) (rv ? 1 : 0); } - unsafe static void GetMethodAndObjectForSelector (IntPtr klass, IntPtr sel, bool is_static, IntPtr obj, IntPtr* mthisPtr, IntPtr desc) + unsafe static void GetMethodAndObjectForSelector (IntPtr klass, IntPtr sel, sbyte is_static, IntPtr obj, IntPtr* mthisPtr, IntPtr desc) { IntPtr mthis = *mthisPtr; - Registrar.GetMethodDescriptionAndObject (Class.Lookup (klass), sel, is_static, obj, ref mthis, desc); + Registrar.GetMethodDescriptionAndObject (Class.Lookup (klass), sel, is_static != 0, obj, ref mthis, desc); *mthisPtr = mthis; } @@ -1899,11 +1902,12 @@ static void RetainNativeObject (IntPtr gchandle) // Check if the input is an NSObject, and in that case retain it (and return true) // This way the caller knows if it can call 'autorelease' on our input. - static bool AttemptRetainNSObject (IntPtr gchandle) + static sbyte AttemptRetainNSObject (IntPtr gchandle) { var obj = GetGCHandleTarget (gchandle) as NSObject; obj?.DangerousRetain (); - return obj is not null; + var rv = obj is not null; + return (sbyte) (rv ? 1 : 0); } #endif // !COREBUILD @@ -2162,12 +2166,13 @@ public static string? OriginalWorkingDirectory { static extern IntPtr xamarin_get_original_working_directory_path (); #endif // NET || !__MACOS__ - static bool InvokeConformsToProtocol (IntPtr handle, IntPtr protocol) + static sbyte InvokeConformsToProtocol (IntPtr handle, IntPtr protocol) { var obj = Runtime.GetNSObject (handle); if (obj is null) - return false; - return obj.ConformsToProtocol (protocol); + return 0; + var rv = obj.ConformsToProtocol (protocol); + return (sbyte) (rv ? 1 : 0); } }