From 6446fba7be367acc3dba53807247ad2442d762f6 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Thu, 22 Feb 2024 13:27:27 -0800 Subject: [PATCH] Address issues discovered after fixing AOT warnings (#1511) * Fix build breaks from AOT warning fixes * Improvements to GUID helper type lookup to avoid needing instantiated generic type * Move around where helper type is initialized to handle more scenarios * Remove commented code --- .../AuthoringConsumptionTest.vcxproj | 2 +- src/Tests/AuthoringConsumptionTest/test.cpp | 3 + src/WinRT.Runtime/ComWrappersSupport.cs | 9 ++ src/WinRT.Runtime/GuidGenerator.cs | 133 +++++++++--------- .../MatchingRefApiCompatBaseline.txt | 3 +- src/WinRT.Runtime/Projections.cs | 2 +- src/WinRT.Runtime/Projections/EventHandler.cs | 5 +- .../Projections/IDictionary.net5.cs | 28 ++-- .../Projections/IEnumerable.net5.cs | 37 +++-- src/WinRT.Runtime/Projections/IList.net5.cs | 47 +++---- .../Projections/IReadOnlyDictionary.net5.cs | 30 ++-- .../Projections/IReadOnlyList.net5.cs | 22 +-- src/WinRT.Runtime/Projections/KeyValuePair.cs | 26 ++-- src/WinRT.Runtime/TypeExtensions.cs | 4 +- src/cswinrt/code_writers.h | 13 +- 15 files changed, 188 insertions(+), 176 deletions(-) diff --git a/src/Tests/AuthoringConsumptionTest/AuthoringConsumptionTest.vcxproj b/src/Tests/AuthoringConsumptionTest/AuthoringConsumptionTest.vcxproj index 3cfc78b70..e8ae95fbe 100644 --- a/src/Tests/AuthoringConsumptionTest/AuthoringConsumptionTest.vcxproj +++ b/src/Tests/AuthoringConsumptionTest/AuthoringConsumptionTest.vcxproj @@ -216,7 +216,7 @@ Use pch.h - X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + X64;NDEBUG;AOT;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase diff --git a/src/Tests/AuthoringConsumptionTest/test.cpp b/src/Tests/AuthoringConsumptionTest/test.cpp index 585078bc3..a1496d1a7 100644 --- a/src/Tests/AuthoringConsumptionTest/test.cpp +++ b/src/Tests/AuthoringConsumptionTest/test.cpp @@ -259,6 +259,8 @@ TEST(AuthoringTest, Arrays) EXPECT_EQ(arr2[idx], idx + 1); } + // Array marshaling on AOT needs dynamic code. +#ifndef AOT std::array basicStructArr; basicStructArr[0] = basicClass.GetBasicStruct(); basicStructArr[1].X = 4; @@ -272,6 +274,7 @@ TEST(AuthoringTest, Arrays) EXPECT_EQ(result[1].X, basicStructArr[1].X); EXPECT_EQ(result[1].Y, basicStructArr[1].Y); EXPECT_EQ(result[1].Value, basicStructArr[1].Value); +#endif } TEST(AuthoringTest, CustomTypes) diff --git a/src/WinRT.Runtime/ComWrappersSupport.cs b/src/WinRT.Runtime/ComWrappersSupport.cs index 1531a7cf8..b88156e83 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.cs @@ -155,6 +155,15 @@ internal static ObjectReference GetObjectReferenceForInterface(IntPtr exte public static void RegisterAuthoringMetadataTypeLookup(Func authoringMetadataTypeLookup) => TypeExtensions.RegisterAuthoringMetadataTypeLookup(authoringMetadataTypeLookup); + public static void RegisterHelperType( + Type type, +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | + DynamicallyAccessedMemberTypes.PublicNestedTypes | + DynamicallyAccessedMemberTypes.PublicFields)] +#endif + Type helperType) => TypeExtensions.HelperTypeCache.TryAdd(type, helperType); + internal static List GetInterfaceTableEntries(Type type) { var entries = new List(); diff --git a/src/WinRT.Runtime/GuidGenerator.cs b/src/WinRT.Runtime/GuidGenerator.cs index 1db5806d7..d2c6f2392 100644 --- a/src/WinRT.Runtime/GuidGenerator.cs +++ b/src/WinRT.Runtime/GuidGenerator.cs @@ -21,7 +21,7 @@ public static Guid GetGUID(Type type) return type.GetGuidType().GUID; } - public static Guid GetIID( + public static Guid GetIID( #if NET [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] #endif @@ -35,21 +35,40 @@ public static Guid GetIID( return (Guid)type.GetField("PIID").GetValue(null); } - public static string GetSignature( + public static string GetSignature( #if NET [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] #endif Type type) - { + { if (type == typeof(object)) { return "cinterface(IInspectable)"; - } - + } + if (type == typeof(string)) { return "string"; - } + } + + if (type.IsGenericType) + { + static string[] SelectSignaturesForTypes(Type[] types) + { + string[] signatures = new string[types.Length]; + + for (int i = 0; i < types.Length; i++) + { + signatures[i] = GetSignature(types[i]); + } + + return signatures; + } + + var args = SelectSignaturesForTypes(type.GetGenericArguments()); + var genericHelperType = type.GetGenericTypeDefinition().FindHelperType() ?? type; + return "pinterface({" + genericHelperType.GUID + "};" + string.Join(";", args) + ")"; + } var helperType = type.FindHelperType(); if (helperType != null) @@ -88,70 +107,52 @@ public static string GetSignature( if (!type.IsPrimitive) { var winrtTypeAttribute = type.GetCustomAttribute(); - if (winrtTypeAttribute != null && !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature)) - { - return winrtTypeAttribute.GuidSignature; + if (winrtTypeAttribute != null && !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature)) + { + return winrtTypeAttribute.GuidSignature; } - else if (winrtTypeAttribute == null && - (winrtTypeAttribute = type.GetAuthoringMetadataType()?.GetCustomAttribute()) != null && - !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature)) - { - return winrtTypeAttribute.GuidSignature; + else if (winrtTypeAttribute == null && + (winrtTypeAttribute = type.GetAuthoringMetadataType()?.GetCustomAttribute()) != null && + !string.IsNullOrEmpty(winrtTypeAttribute.GuidSignature)) + { + return winrtTypeAttribute.GuidSignature; } - else - { - static string[] SelectSignaturesForFields(FieldInfo[] fields) - { - string[] signatures = new string[fields.Length]; - - for (int i = 0; i < fields.Length; i++) - { - signatures[i] = GetSignature(fields[i].FieldType); - } - - return signatures; - } - - var args = SelectSignaturesForFields(type.GetFields(BindingFlags.Instance | BindingFlags.Public)); - return "struct(" + type.FullName + ";" + String.Join(";", args) + ")"; + else + { + static string[] SelectSignaturesForFields(FieldInfo[] fields) + { + string[] signatures = new string[fields.Length]; + + for (int i = 0; i < fields.Length; i++) + { + signatures[i] = GetSignature(fields[i].FieldType); + } + + return signatures; + } + + var args = SelectSignaturesForFields(type.GetFields(BindingFlags.Instance | BindingFlags.Public)); + return "struct(" + type.FullName + ";" + String.Join(";", args) + ")"; } } throw new InvalidOperationException("unsupported value type"); } } } - - // For authoring interfaces, we can use the metadata type or the helper type to get the guid. - // For built-in system interfaces that are custom type mapped, we use the helper type to get the guid. - // For others, either the type itself or the helper type has the same guid and can be used. - type = type.IsInterface ? (helperType ?? type) : type; - if (type.IsGenericType) - { - static string[] SelectSignaturesForTypes(Type[] types) - { - string[] signatures = new string[types.Length]; - - for (int i = 0; i < types.Length; i++) - { - signatures[i] = GetSignature(types[i]); - } - - return signatures; - } + // For authoring interfaces, we can use the metadata type or the helper type to get the guid. + // For built-in system interfaces that are custom type mapped, we use the helper type to get the guid. + // For others, either the type itself or the helper type has the same guid and can be used. + type = type.IsInterface ? (helperType ?? type) : type; - var args = SelectSignaturesForTypes(type.GetGenericArguments()); - return "pinterface({" + GetGUID(type) + "};" + String.Join(";", args) + ")"; - } - if (type.IsDelegate()) { return "delegate({" + GetGUID(type) + "})"; - } - - if (type.IsClass && Projections.TryGetDefaultInterfaceTypeForRuntimeClassType(type, out Type iface)) - { - return "rc(" + type.FullName + ";" + GetSignature(iface) + ")"; + } + + if (type.IsClass && Projections.TryGetDefaultInterfaceTypeForRuntimeClassType(type, out Type iface)) + { + return "rc(" + type.FullName + ";" + GetSignature(iface) + ")"; } return "{" + type.GUID.ToString() + "}"; @@ -195,14 +196,14 @@ public static Guid CreateIID(Type type) { return new Guid(sig); } - else - { - return CreateIIDForGenericType(sig); + else + { + return CreateIIDForGenericType(sig); } } - internal static Guid CreateIIDForGenericType(string signature) - { + internal static Guid CreateIIDForGenericType(string signature) + { #if !NET var data = System.Linq.Enumerable.ToArray(System.Linq.Enumerable.Concat(wrt_pinterface_namespace.ToByteArray(), Encoding.UTF8.GetBytes(signature))); @@ -217,10 +218,10 @@ internal static Guid CreateIIDForGenericType(string signature) Span dataSpan = data; wrt_pinterface_namespace.TryWriteBytes(dataSpan); var numBytes = UTF8Encoding.UTF8.GetBytes(signature, dataSpan[16..]); - data = data[..(16 + numBytes)]; - - return encode_guid(SHA1.HashData(data)); -#endif + data = data[..(16 + numBytes)]; + + return encode_guid(SHA1.HashData(data)); +#endif } } } diff --git a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt index a3894ea0b..c6ddafc10 100644 --- a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt +++ b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt @@ -210,4 +210,5 @@ CannotRemoveAttribute : Attribute 'System.ObsoleteAttribute' exists on 'ABI.WinR CannotRemoveAttribute : Attribute 'System.ComponentModel.EditorBrowsableAttribute' exists on 'WinRT.IObjectReference.AsType()' in the implementation but not the reference. CannotRemoveAttribute : Attribute 'System.ObsoleteAttribute' exists on 'WinRT.IObjectReference.AsType()' in the implementation but not the reference. CannotRemoveAttribute : Attribute 'System.ObsoleteAttribute' exists on 'System.Type WinRT.Marshaler.RefAbiType' in the implementation but not the reference. -Total Issues: 211 +MembersMustExist : Member 'public void WinRT.ComWrappersSupport.RegisterHelperType(System.Type, System.Type)' does not exist in the reference but it does exist in the implementation. +Total Issues: 212 diff --git a/src/WinRT.Runtime/Projections.cs b/src/WinRT.Runtime/Projections.cs index 0e7460ae7..2422ce311 100644 --- a/src/WinRT.Runtime/Projections.cs +++ b/src/WinRT.Runtime/Projections.cs @@ -261,7 +261,7 @@ public static Type FindCustomHelperTypeMapping(Type publicType, bool filterToRun return null; } - if (publicType.IsGenericType) + if (publicType.IsGenericType && !publicType.IsGenericTypeDefinition) { if (CustomTypeToHelperTypeMappings.TryGetValue(publicType, out Type specializedAbiType)) { diff --git a/src/WinRT.Runtime/Projections/EventHandler.cs b/src/WinRT.Runtime/Projections/EventHandler.cs index 1e04c76fb..81b0f4fcf 100644 --- a/src/WinRT.Runtime/Projections/EventHandler.cs +++ b/src/WinRT.Runtime/Projections/EventHandler.cs @@ -121,6 +121,9 @@ static class EventHandler static unsafe EventHandler() { + ComWrappersSupport.RegisterHelperType(typeof(global::System.EventHandler), typeof(global::ABI.System.EventHandler)); + ComWrappersSupport.RegisterDelegateFactory(typeof(global::System.EventHandler), CreateRcw); + #if NET if (!RuntimeFeature.IsDynamicCodeCompiled) { @@ -152,8 +155,6 @@ static unsafe EventHandler() ((IntPtr*)AbiToProjectionVftablePtr)[3] = Marshal.GetFunctionPointerForDelegate(AbiInvokeDelegate); #pragma warning restore IL3050 } - - ComWrappersSupport.RegisterDelegateFactory(typeof(global::System.EventHandler), CreateRcw); } public static global::System.Delegate AbiInvokeDelegate { get; } diff --git a/src/WinRT.Runtime/Projections/IDictionary.net5.cs b/src/WinRT.Runtime/Projections/IDictionary.net5.cs index da25c5915..a19a17411 100644 --- a/src/WinRT.Runtime/Projections/IDictionary.net5.cs +++ b/src/WinRT.Runtime/Projections/IDictionary.net5.cs @@ -252,6 +252,8 @@ static class IDictionaryMethods { unsafe static IDictionaryMethods() { + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IDictionary), typeof(global::ABI.System.Collections.Generic.IDictionary)); + // Early return to ensure things are trimmed correctly on NAOT. // See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md. if (!RuntimeFeature.IsDynamicCodeCompiled) @@ -855,6 +857,9 @@ public static unsafe bool InitCcw( return false; } + // Register generic helper types referenced in CCW. + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IReadOnlyDictionary), typeof(global::ABI.System.Collections.Generic.IReadOnlyDictionary)); + return true; } @@ -876,20 +881,15 @@ internal static unsafe void InitFallbackCCWVtable() new IDictionary_Delegates.Clear_6(Do_Abi_Clear_6) }; - var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 7)); - *(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable; - ((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache[0]); - ((IntPtr*)abiToProjectionVftablePtr)[7] = Marshal.GetFunctionPointerForDelegate(DelegateCache[1]); - ((IntPtr*)abiToProjectionVftablePtr)[8] = Marshal.GetFunctionPointerForDelegate(DelegateCache[2]); - ((IntPtr*)abiToProjectionVftablePtr)[9] = Marshal.GetFunctionPointerForDelegate(DelegateCache[3]); - ((IntPtr*)abiToProjectionVftablePtr)[10] = Marshal.GetFunctionPointerForDelegate(DelegateCache[4]); - ((IntPtr*)abiToProjectionVftablePtr)[11] = Marshal.GetFunctionPointerForDelegate(DelegateCache[5]); - ((IntPtr*)abiToProjectionVftablePtr)[12] = Marshal.GetFunctionPointerForDelegate(DelegateCache[6]); - - if (!IDictionaryMethods.TryInitCCWVtable(abiToProjectionVftablePtr)) - { - NativeMemory.Free((void*)abiToProjectionVftablePtr); - } + InitCcw( + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[0]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[1]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[2]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[3]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[4]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[5]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[6]) + ); } private static unsafe int Do_Abi_Lookup_0(void* thisPtr, KAbi key, VAbi* __return_value__) diff --git a/src/WinRT.Runtime/Projections/IEnumerable.net5.cs b/src/WinRT.Runtime/Projections/IEnumerable.net5.cs index 26768282b..087592f5f 100644 --- a/src/WinRT.Runtime/Projections/IEnumerable.net5.cs +++ b/src/WinRT.Runtime/Projections/IEnumerable.net5.cs @@ -220,6 +220,11 @@ namespace ABI.System.Collections.Generic #endif static class IEnumerableMethods { + static IEnumerableMethods() + { + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IEnumerable), typeof(global::ABI.System.Collections.Generic.IEnumerable)); + } + public static global::System.Collections.Generic.IEnumerator GetEnumerator(IObjectReference obj) { var first = ABI.Windows.Foundation.Collections.IIterableMethods.First(obj); @@ -294,6 +299,9 @@ public static unsafe bool InitCcw( return false; } + // Register generic helper types referenced in CCW. + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IEnumerator), typeof(global::ABI.System.Collections.Generic.IEnumerator)); + return true; } @@ -302,15 +310,7 @@ public static unsafe bool InitCcw( internal static unsafe void InitFallbackCCWVtable() { DelegateCache = new IEnumerable_Delegates.First_0_Abi(Do_Abi_First_0); - - var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 1)); - *(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable; - ((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache); - - if (!IEnumerableMethods.TryInitCCWVtable(abiToProjectionVftablePtr)) - { - NativeMemory.Free((void*)abiToProjectionVftablePtr); - } + InitCcw((delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache)); } private static unsafe int Do_Abi_First_0(IntPtr thisPtr, IntPtr* __return_value__) @@ -516,6 +516,8 @@ static class IEnumeratorMethods { unsafe static IEnumeratorMethods() { + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IEnumerator), typeof(global::ABI.System.Collections.Generic.IEnumerator)); + // Early return to ensure things are trimmed correctly on NAOT. // See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md. if (!RuntimeFeature.IsDynamicCodeCompiled) @@ -677,17 +679,12 @@ internal static unsafe void InitFallbackCCWVtable() new IEnumerator_Delegates.GetMany_3_Abi(Do_Abi_GetMany_3) }; - var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 4)); - *(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable; - ((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache[0]); - ((IntPtr*)abiToProjectionVftablePtr)[7] = Marshal.GetFunctionPointerForDelegate(DelegateCache[1]); - ((IntPtr*)abiToProjectionVftablePtr)[8] = Marshal.GetFunctionPointerForDelegate(DelegateCache[2]); - ((IntPtr*)abiToProjectionVftablePtr)[9] = Marshal.GetFunctionPointerForDelegate(DelegateCache[3]); - - if (!IEnumeratorMethods.TryInitCCWVtable(abiToProjectionVftablePtr)) - { - NativeMemory.Free((void*)abiToProjectionVftablePtr); - } + InitCcw( + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[0]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[1]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[2]), + (delegate* unmanaged[Stdcall]) Marshal.GetFunctionPointerForDelegate(DelegateCache[3]) + ); } private static unsafe int Do_Abi_MoveNext_2(IntPtr thisPtr, byte* __return_value__) diff --git a/src/WinRT.Runtime/Projections/IList.net5.cs b/src/WinRT.Runtime/Projections/IList.net5.cs index 932693f7c..8bd2db59a 100644 --- a/src/WinRT.Runtime/Projections/IList.net5.cs +++ b/src/WinRT.Runtime/Projections/IList.net5.cs @@ -158,7 +158,9 @@ namespace ABI.System.Collections.Generic static class IListMethods { unsafe static IListMethods() - { + { + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IList), typeof(global::ABI.System.Collections.Generic.IList)); + // Early return to ensure things are trimmed correctly on NAOT. // See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md. if (!RuntimeFeature.IsDynamicCodeCompiled) @@ -439,7 +441,7 @@ internal unsafe static bool EnsureEnumerableInitialized() public #endif static class IListMethods where TAbi : unmanaged - { + { public unsafe static bool InitRcwHelper( delegate* getAt, delegate*> getView, @@ -624,7 +626,9 @@ public static unsafe bool InitCcw( { NativeMemory.Free((void*)abiToProjectionVftablePtr); return false; - } + } + + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IReadOnlyList), typeof(global::ABI.System.Collections.Generic.IReadOnlyList)); return true; } @@ -652,27 +656,22 @@ internal static unsafe void InitFallbackCCWVtable() new IList_Delegates.Clear_9(Do_Abi_Clear_9), new IList_Delegates.GetMany_10_Abi(Do_Abi_GetMany_10), new IList_Delegates.ReplaceAll_11(Do_Abi_ReplaceAll_11) - }; - - var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 12)); - *(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable; - ((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache[0]); - ((IntPtr*)abiToProjectionVftablePtr)[7] = Marshal.GetFunctionPointerForDelegate(DelegateCache[1]); - ((IntPtr*)abiToProjectionVftablePtr)[8] = Marshal.GetFunctionPointerForDelegate(DelegateCache[2]); - ((IntPtr*)abiToProjectionVftablePtr)[9] = Marshal.GetFunctionPointerForDelegate(DelegateCache[3]); - ((IntPtr*)abiToProjectionVftablePtr)[10] = Marshal.GetFunctionPointerForDelegate(DelegateCache[4]); - ((IntPtr*)abiToProjectionVftablePtr)[11] = Marshal.GetFunctionPointerForDelegate(DelegateCache[5]); - ((IntPtr*)abiToProjectionVftablePtr)[12] = Marshal.GetFunctionPointerForDelegate(DelegateCache[6]); - ((IntPtr*)abiToProjectionVftablePtr)[13] = Marshal.GetFunctionPointerForDelegate(DelegateCache[7]); - ((IntPtr*)abiToProjectionVftablePtr)[14] = Marshal.GetFunctionPointerForDelegate(DelegateCache[8]); - ((IntPtr*)abiToProjectionVftablePtr)[15] = Marshal.GetFunctionPointerForDelegate(DelegateCache[9]); - ((IntPtr*)abiToProjectionVftablePtr)[16] = Marshal.GetFunctionPointerForDelegate(DelegateCache[10]); - ((IntPtr*)abiToProjectionVftablePtr)[17] = Marshal.GetFunctionPointerForDelegate(DelegateCache[11]); - - if (!IListMethods.TryInitCCWVtable(abiToProjectionVftablePtr)) - { - NativeMemory.Free((void*)abiToProjectionVftablePtr); - } + }; + + InitCcw( + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[0]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[1]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[2]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[3]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[4]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[5]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[6]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[7]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[8]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[9]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[10]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[11]) + ); } private static unsafe int Do_Abi_GetAt_0(void* thisPtr, uint index, TAbi* __return_value__) diff --git a/src/WinRT.Runtime/Projections/IReadOnlyDictionary.net5.cs b/src/WinRT.Runtime/Projections/IReadOnlyDictionary.net5.cs index 7bd8dd4e0..1b5425607 100644 --- a/src/WinRT.Runtime/Projections/IReadOnlyDictionary.net5.cs +++ b/src/WinRT.Runtime/Projections/IReadOnlyDictionary.net5.cs @@ -183,7 +183,10 @@ namespace ABI.System.Collections.Generic static class IReadOnlyDictionaryMethods { unsafe static IReadOnlyDictionaryMethods() - { + { + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IReadOnlyDictionary), typeof(global::ABI.System.Collections.Generic.IReadOnlyDictionary)); + ComWrappersSupport.RegisterHelperType(typeof(global::Windows.Foundation.Collections.IMapView), typeof(global::ABI.System.Collections.Generic.IReadOnlyDictionary)); + // Early return to ensure things are trimmed correctly on NAOT. // See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md. if (!RuntimeFeature.IsDynamicCodeCompiled) @@ -440,7 +443,7 @@ public static uint Abi_get_Size_1(IntPtr thisPtr) public #endif static class IReadOnlyDictionaryMethods where KAbi : unmanaged where VAbi : unmanaged - { + { public unsafe static bool InitRcwHelper( delegate* lookup, delegate* hasKey, @@ -539,7 +542,7 @@ public static unsafe bool InitCcw( { NativeMemory.Free((void*)abiToProjectionVftablePtr); return false; - } + } return true; } @@ -557,19 +560,14 @@ internal static unsafe void InitFallbackCCWVtable() new _get_PropertyAsUInt32_Abi(Do_Abi_get_Size_1), global::System.Delegate.CreateDelegate(HasKey_2_Type, typeof(IReadOnlyDictionaryMethods).GetMethod(nameof(Do_Abi_HasKey_2), BindingFlags.NonPublic | BindingFlags.Static)), new IReadOnlyDictionary_Delegates.Split_3_Abi(Do_Abi_Split_3), - }; - - var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 4)); - *(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable; - ((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache[0]); - ((IntPtr*)abiToProjectionVftablePtr)[7] = Marshal.GetFunctionPointerForDelegate(DelegateCache[1]); - ((IntPtr*)abiToProjectionVftablePtr)[8] = Marshal.GetFunctionPointerForDelegate(DelegateCache[2]); - ((IntPtr*)abiToProjectionVftablePtr)[9] = Marshal.GetFunctionPointerForDelegate(DelegateCache[3]); - - if (!IReadOnlyDictionaryMethods.TryInitCCWVtable(abiToProjectionVftablePtr)) - { - NativeMemory.Free((void*)abiToProjectionVftablePtr); - } + }; + + InitCcw( + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[0]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[1]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[2]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[3]) + ); } private static unsafe int Do_Abi_Lookup_0(IntPtr thisPtr, KAbi key, VAbi* __return_value__) diff --git a/src/WinRT.Runtime/Projections/IReadOnlyList.net5.cs b/src/WinRT.Runtime/Projections/IReadOnlyList.net5.cs index 51588304b..9e207ae9a 100644 --- a/src/WinRT.Runtime/Projections/IReadOnlyList.net5.cs +++ b/src/WinRT.Runtime/Projections/IReadOnlyList.net5.cs @@ -202,6 +202,11 @@ namespace ABI.System.Collections.Generic #endif static class IReadOnlyListMethods { + static IReadOnlyListMethods() + { + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.IReadOnlyList), typeof(global::ABI.System.Collections.Generic.IReadOnlyList)); + } + public static int get_Count(IObjectReference obj) { uint size = ABI.Windows.Foundation.Collections.IVectorViewMethods.get_Size(obj); @@ -383,17 +388,12 @@ internal static unsafe void InitFallbackCCWVtable() new IReadOnlyList_Delegates.GetMany_3_Abi(Do_Abi_GetMany_3) }; - var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 4)); - *(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable; - ((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache[0]); - ((IntPtr*)abiToProjectionVftablePtr)[7] = Marshal.GetFunctionPointerForDelegate(DelegateCache[1]); - ((IntPtr*)abiToProjectionVftablePtr)[8] = Marshal.GetFunctionPointerForDelegate(DelegateCache[2]); - ((IntPtr*)abiToProjectionVftablePtr)[9] = Marshal.GetFunctionPointerForDelegate(DelegateCache[3]); - - if (!IReadOnlyListMethods.TryInitCCWVtable(abiToProjectionVftablePtr)) - { - NativeMemory.Free((void*)abiToProjectionVftablePtr); - } + InitCcw( + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[0]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[1]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[2]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[3]) + ); } private static unsafe int Do_Abi_GetAt_0(IntPtr thisPtr, uint index, TAbi* __return_value__) diff --git a/src/WinRT.Runtime/Projections/KeyValuePair.cs b/src/WinRT.Runtime/Projections/KeyValuePair.cs index e6f88a0eb..28760b60b 100644 --- a/src/WinRT.Runtime/Projections/KeyValuePair.cs +++ b/src/WinRT.Runtime/Projections/KeyValuePair.cs @@ -42,6 +42,11 @@ static class KeyValuePairMethods internal volatile unsafe static delegate* _GetValue; internal volatile static bool _RcwHelperInitialized; + static KeyValuePairMethods() + { + ComWrappersSupport.RegisterHelperType(typeof(global::System.Collections.Generic.KeyValuePair), typeof(global::ABI.System.Collections.Generic.KeyValuePair)); + } + internal static unsafe bool EnsureInitialized() { #if NET @@ -220,23 +225,10 @@ internal static unsafe void InitFallbackCCWVtable() global::System.Delegate.CreateDelegate(get_Value_1_Type, typeof(KeyValuePairMethods).GetMethod(nameof(Do_Abi_get_Value_1), BindingFlags.NonPublic | BindingFlags.Static)), }; -#if NET - var abiToProjectionVftablePtr = (IntPtr)NativeMemory.AllocZeroed((nuint)(sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 2)); -#else - var abiToProjectionVftablePtr = (IntPtr)Marshal.AllocCoTaskMem((sizeof(IInspectable.Vftbl) + sizeof(IntPtr) * 2)); -#endif - *(IInspectable.Vftbl*)abiToProjectionVftablePtr = IInspectable.Vftbl.AbiToProjectionVftable; - ((IntPtr*)abiToProjectionVftablePtr)[6] = Marshal.GetFunctionPointerForDelegate(DelegateCache[0]); - ((IntPtr*)abiToProjectionVftablePtr)[7] = Marshal.GetFunctionPointerForDelegate(DelegateCache[1]); - - if (!KeyValuePairMethods.TryInitCCWVtable(abiToProjectionVftablePtr)) - { -#if NET - NativeMemory.Free((void*)abiToProjectionVftablePtr); -#else - Marshal.FreeCoTaskMem(abiToProjectionVftablePtr); -#endif - } + InitCcw( + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[0]), + (delegate* unmanaged[Stdcall])Marshal.GetFunctionPointerForDelegate(DelegateCache[1]) + ); } private static unsafe int Do_Abi_get_Key_0(IntPtr thisPtr, KAbi* __return_value__) diff --git a/src/WinRT.Runtime/TypeExtensions.cs b/src/WinRT.Runtime/TypeExtensions.cs index eb0092267..b716f36ea 100644 --- a/src/WinRT.Runtime/TypeExtensions.cs +++ b/src/WinRT.Runtime/TypeExtensions.cs @@ -17,7 +17,7 @@ namespace WinRT #endif static class TypeExtensions { - private readonly static ConcurrentDictionary HelperTypeCache = new ConcurrentDictionary(); + internal readonly static ConcurrentDictionary HelperTypeCache = new ConcurrentDictionary(); #if NET [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | @@ -79,7 +79,7 @@ public static Type FindHelperType(this Type type) #endif static Type GetHelperTypeFromAttribute(WindowsRuntimeHelperTypeAttribute helperTypeAtribute, Type type) { - if (type.IsGenericType) + if (type.IsGenericType && !type.IsGenericTypeDefinition) { #if NET if (!RuntimeFeature.IsDynamicCodeCompiled) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index b68acb77a..a4fa65094 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -6106,7 +6106,7 @@ return eventSource.EventActions; auto guard{ w.push_generic_args(type) }; set_typedef_marshaler(type.generic_type); - if (!settings.netstandard_compat && (!m.is_out() || get_category(type.generic_type) == category::delegate_type)) + if (!settings.netstandard_compat) { auto generic_instantiation_class_name = get_generic_instantiation_class_type_name(w, type.generic_type); if (!starts_with(generic_instantiation_class_name, "Windows_Foundation_IReference")) @@ -7412,6 +7412,7 @@ internal static global::System.Guid IID { get; } = new Guid(new byte[] { % }); internal volatile static bool _RcwHelperInitialized; unsafe static @Methods() { +ComWrappersSupport.RegisterHelperType(typeof(%), typeof(%)); if (RuntimeFeature.IsDynamicCodeCompiled && !_RcwHelperInitialized) { var ensureInitializedFallback = (Func)typeof(@Methods<%>).MakeGenericType(%). @@ -7422,6 +7423,8 @@ ensureInitializedFallback(); } )", iface.TypeName(), + bind(iface, typedef_name_type::Projected, false), + bind(iface, typedef_name_type::ABI, false), iface.TypeName(), bind([&](writer& w) { @@ -9089,6 +9092,11 @@ internal static class % private static IntPtr abiToProjectionVftablePtr; internal static IntPtr AbiToProjectionVftablePtr => abiToProjectionVftablePtr; +static @Methods() +{ +ComWrappersSupport.RegisterHelperType(typeof(%), typeof(%)); +} + internal static bool TryInitCCWVtable(IntPtr ptr) { bool success = global::System.Threading.Interlocked.CompareExchange(ref abiToProjectionVftablePtr, ptr, IntPtr.Zero) == IntPtr.Zero; @@ -9146,6 +9154,9 @@ public static % Abi_Invoke(IntPtr thisPtr%%) bind_list(", ", signature.params()), signature.has_params() ? ", " : "", bind(signature)), + type.TypeName(), + bind(type, typedef_name_type::Projected, false), + bind(type, typedef_name_type::ABI, false), bind(type, typedef_name_type::ABI, false), bind(type, typedef_name_type::Projected, false), bind(type, typedef_name_type::Projected, false),