From 2306c5acfdf2b3e94a8f4c8ac11e83e0058f35d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 7 Mar 2023 12:20:52 +0900 Subject: [PATCH 1/4] Make open method resolver pay for play Resolver is called into from delegate thunks, so we can't get rid of it, but to construct a resolver one needs to do some reflection first. Make the resolution logic statically depend on resolver being constructed. --- .../Runtime/CompilerServices/OpenMethodResolver.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs index b4fffe59189370..e85ec120d5d1a8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs @@ -20,8 +20,10 @@ namespace Internal.Runtime.CompilerServices // 3) Use the ResolveMethod function to do the virtual lookup. This function takes advantage of // a lockless cache so the resolution is very fast for repeated lookups. [ReflectionBlocked] - public struct OpenMethodResolver : IEquatable + public unsafe struct OpenMethodResolver : IEquatable { + private static delegate* s_lazyGvmLookupForSlot; + public const short DispatchResolve = 0; public const short GVMResolve = 1; public const short OpenNonVirtualResolve = 2; @@ -42,6 +44,7 @@ public OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, int slot, GCHan _handle = handle; _readerGCHandle = readerGCHandle; _nonVirtualOpenInvokeCodePointer = IntPtr.Zero; + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public unsafe OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, RuntimeMethodHandle gvmSlot, GCHandle readerGCHandle, int handle) @@ -52,6 +55,7 @@ public unsafe OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, RuntimeM _handle = handle; _readerGCHandle = readerGCHandle; _nonVirtualOpenInvokeCodePointer = IntPtr.Zero; + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, GCHandle readerGCHandle, int handle) @@ -61,6 +65,7 @@ public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, G _declaringType = declaringType.ToEETypePtr(); _handle = handle; _readerGCHandle = readerGCHandle; + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, GCHandle readerGCHandle, int handle, short resolveType) @@ -76,6 +81,7 @@ public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, G _nonVirtualOpenInvokeCodePointer = RuntimeAugments.TypeLoaderCallbacks.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(codePointer, declaringType); else throw new NotSupportedException(); + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public short ResolverType @@ -151,7 +157,7 @@ private unsafe IntPtr ResolveMethod(object thisObject) } else if (_resolveType == GVMResolve) { - return TypeLoaderExports.GVMLookupForSlot(thisObject, GVMMethodHandle); + return s_lazyGvmLookupForSlot(thisObject, GVMMethodHandle); } else { From a3bc4a61753867ba1df8e4aa5b72801f9d0fa1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 7 Mar 2023 16:29:14 +0900 Subject: [PATCH 2/4] Update OpenMethodResolver.cs --- .../CompilerServices/OpenMethodResolver.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs index e85ec120d5d1a8..fdd39789374d64 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs @@ -22,6 +22,7 @@ namespace Internal.Runtime.CompilerServices [ReflectionBlocked] public unsafe struct OpenMethodResolver : IEquatable { + // Lazy initialized to point to the type loader method when the first `GVMResolve` resolver is created private static delegate* s_lazyGvmLookupForSlot; public const short DispatchResolve = 0; @@ -44,7 +45,9 @@ public OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, int slot, GCHan _handle = handle; _readerGCHandle = readerGCHandle; _nonVirtualOpenInvokeCodePointer = IntPtr.Zero; - s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; + + if (s_lazyGvmLookupForSlot == IntPtr.Zero) + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public unsafe OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, RuntimeMethodHandle gvmSlot, GCHandle readerGCHandle, int handle) @@ -55,7 +58,9 @@ public unsafe OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, RuntimeM _handle = handle; _readerGCHandle = readerGCHandle; _nonVirtualOpenInvokeCodePointer = IntPtr.Zero; - s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; + + if (s_lazyGvmLookupForSlot == IntPtr.Zero) + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, GCHandle readerGCHandle, int handle) @@ -65,7 +70,9 @@ public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, G _declaringType = declaringType.ToEETypePtr(); _handle = handle; _readerGCHandle = readerGCHandle; - s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; + + if (s_lazyGvmLookupForSlot == IntPtr.Zero) + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, GCHandle readerGCHandle, int handle, short resolveType) @@ -81,7 +88,9 @@ public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, G _nonVirtualOpenInvokeCodePointer = RuntimeAugments.TypeLoaderCallbacks.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(codePointer, declaringType); else throw new NotSupportedException(); - s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; + + if (s_lazyGvmLookupForSlot == IntPtr.Zero) + s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public short ResolverType From 03f5cb2822f0a49d93d0000570d91f759299d6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 7 Mar 2023 16:31:53 +0900 Subject: [PATCH 3/4] Update OpenMethodResolver.cs --- .../Runtime/CompilerServices/OpenMethodResolver.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs index fdd39789374d64..1c10ff88d2d6f5 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs @@ -45,9 +45,6 @@ public OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, int slot, GCHan _handle = handle; _readerGCHandle = readerGCHandle; _nonVirtualOpenInvokeCodePointer = IntPtr.Zero; - - if (s_lazyGvmLookupForSlot == IntPtr.Zero) - s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public unsafe OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, RuntimeMethodHandle gvmSlot, GCHandle readerGCHandle, int handle) @@ -70,9 +67,6 @@ public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, G _declaringType = declaringType.ToEETypePtr(); _handle = handle; _readerGCHandle = readerGCHandle; - - if (s_lazyGvmLookupForSlot == IntPtr.Zero) - s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, GCHandle readerGCHandle, int handle, short resolveType) @@ -88,9 +82,6 @@ public OpenMethodResolver(RuntimeTypeHandle declaringType, IntPtr codePointer, G _nonVirtualOpenInvokeCodePointer = RuntimeAugments.TypeLoaderCallbacks.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(codePointer, declaringType); else throw new NotSupportedException(); - - if (s_lazyGvmLookupForSlot == IntPtr.Zero) - s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; } public short ResolverType From d5091eda999bb100ea3101ca105ae9082afb696a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 7 Mar 2023 16:50:35 +0900 Subject: [PATCH 4/4] Update OpenMethodResolver.cs --- .../Internal/Runtime/CompilerServices/OpenMethodResolver.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs index 1c10ff88d2d6f5..b9a5b1353499f2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs @@ -20,10 +20,10 @@ namespace Internal.Runtime.CompilerServices // 3) Use the ResolveMethod function to do the virtual lookup. This function takes advantage of // a lockless cache so the resolution is very fast for repeated lookups. [ReflectionBlocked] - public unsafe struct OpenMethodResolver : IEquatable + public struct OpenMethodResolver : IEquatable { // Lazy initialized to point to the type loader method when the first `GVMResolve` resolver is created - private static delegate* s_lazyGvmLookupForSlot; + private static unsafe delegate* s_lazyGvmLookupForSlot; public const short DispatchResolve = 0; public const short GVMResolve = 1; @@ -56,7 +56,7 @@ public unsafe OpenMethodResolver(RuntimeTypeHandle declaringTypeOfSlot, RuntimeM _readerGCHandle = readerGCHandle; _nonVirtualOpenInvokeCodePointer = IntPtr.Zero; - if (s_lazyGvmLookupForSlot == IntPtr.Zero) + if (s_lazyGvmLookupForSlot == null) s_lazyGvmLookupForSlot = &TypeLoaderExports.GVMLookupForSlot; }