From 3b5921c661f82291b7f63aee12e54e4b96d040dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Mon, 16 Jan 2023 13:52:00 +0900 Subject: [PATCH] Make reading custom attributes in NativeLibrary avoidable Contributes to #80165. Unfortunately, the `NativeLibrary` APIs contain a pattern where one can skip providing a parameter to the API and then something expensive (custom attribute reading) will happen to compute the value. We have a `TryLoad` call in a hello world that does provide the value (in GlobalizationMode.cs). Make it possible to avoid the expensive thing internally. --- .../NativeLibrary.NativeAot.cs | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs index 3708b256808e8..d79088ae9b4f0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs @@ -10,23 +10,34 @@ namespace System.Runtime.InteropServices { public static partial class NativeLibrary { + // Not a public API. We expose this so that it's possible to bypass the codepath that tries to read search path + // from custom attributes. + internal static bool TryLoad(string libraryName, Assembly assembly, DllImportSearchPath searchPath, out IntPtr handle) + { + handle = LoadLibraryByName(libraryName, + assembly, + searchPath, + throwOnError: false); + return handle != IntPtr.Zero; + } + internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, bool throwOnError) { // First checks if a default dllImportSearchPathFlags was passed in, if so, use that value. // Otherwise checks if the assembly has the DefaultDllImportSearchPathsAttribute attribute. // If so, use that value. - int searchPathFlags; - bool searchAssemblyDirectory; - if (searchPath.HasValue) - { - searchPathFlags = (int)(searchPath.Value & ~DllImportSearchPath.AssemblyDirectory); - searchAssemblyDirectory = (searchPath.Value & DllImportSearchPath.AssemblyDirectory) != 0; - } - else + if (!searchPath.HasValue) { - GetDllImportSearchPathFlags(assembly, out searchPathFlags, out searchAssemblyDirectory); + searchPath = GetDllImportSearchPath(assembly); } + return LoadLibraryByName(libraryName, assembly, searchPath.Value, throwOnError); + } + + internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, DllImportSearchPath searchPath, bool throwOnError) + { + int searchPathFlags = (int)(searchPath & ~DllImportSearchPath.AssemblyDirectory); + bool searchAssemblyDirectory = (searchPath & DllImportSearchPath.AssemblyDirectory) != 0; LoadLibErrorTracker errorTracker = default; IntPtr ret = LoadBySearch(assembly, searchAssemblyDirectory, searchPathFlags, ref errorTracker, libraryName); @@ -38,20 +49,17 @@ internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, return ret; } - internal static void GetDllImportSearchPathFlags(Assembly callingAssembly, out int searchPathFlags, out bool searchAssemblyDirectory) + internal static DllImportSearchPath GetDllImportSearchPath(Assembly callingAssembly) { - var searchPath = DllImportSearchPath.AssemblyDirectory; - foreach (CustomAttributeData cad in callingAssembly.CustomAttributes) { if (cad.AttributeType == typeof(DefaultDllImportSearchPathsAttribute)) { - searchPath = (DllImportSearchPath)cad.ConstructorArguments[0].Value!; + return (DllImportSearchPath)cad.ConstructorArguments[0].Value!; } } - searchPathFlags = (int)(searchPath & ~DllImportSearchPath.AssemblyDirectory); - searchAssemblyDirectory = (searchPath & DllImportSearchPath.AssemblyDirectory) != 0; + return DllImportSearchPath.AssemblyDirectory; } internal static IntPtr LoadBySearch(Assembly callingAssembly, bool searchAssemblyDirectory, int dllImportSearchPathFlags, ref LoadLibErrorTracker errorTracker, string libraryName)