From 239fca5133588dbd32a0b21500a8dd8214f38ff6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 16 May 2023 06:33:42 +0900 Subject: [PATCH] Delete some code around `ModuleList` (#86230) The concept of loading modules on demand never existed outside some internal ProjectN branches. Delete some code around it. Also delete an extra enumerator that was only used in one place. --- .../StackTraceMetadata/StackTraceMetadata.cs | 6 +- .../Execution/AssemblyBinderImplementation.cs | 15 +- .../src/Internal/Runtime/TypeLoader/ModuleList.cs | 218 +++------------------ .../TypeLoaderEnvironment.GVMResolution.cs | 2 +- .../TypeLoaderEnvironment.SignatureParsing.cs | 4 +- .../Runtime/TypeLoader/TypeLoaderEnvironment.cs | 17 +- 6 files changed, 37 insertions(+), 225 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs index 9e95dd3..416b553 100644 --- a/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs +++ b/src/coreclr/nativeaot/System.Private.StackTraceMetadata/src/Internal/StackTraceMetadata/StackTraceMetadata.cs @@ -44,11 +44,11 @@ namespace Internal.StackTraceMetadata { IntPtr moduleStartAddress = RuntimeAugments.GetOSModuleFromPointer(methodStartAddress); int rva = (int)((byte*)methodStartAddress - (byte*)moduleStartAddress); - foreach (TypeManagerHandle handle in ModuleList.Enumerate()) + foreach (NativeFormatModuleInfo moduleInfo in ModuleList.EnumerateModules()) { - if (handle.OsModuleBase == moduleStartAddress) + if (moduleInfo.Handle.OsModuleBase == moduleStartAddress) { - string name = _perModuleMethodNameResolverHashtable.GetOrCreateValue(handle.GetIntPtrUNSAFE()).GetMethodNameFromRvaIfAvailable(rva); + string name = _perModuleMethodNameResolverHashtable.GetOrCreateValue(moduleInfo.Handle.GetIntPtrUNSAFE()).GetMethodNameFromRvaIfAvailable(rva); if (name != null) return name; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs index 9ea91a3..dd3f3da 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs @@ -28,7 +28,9 @@ namespace Internal.Reflection.Execution private AssemblyBinderImplementation() { _scopeGroups = new KeyValuePair[0]; - ModuleList.AddModuleRegistrationCallback(RegisterModule); + + foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules()) + RegisterModule(module); } public static AssemblyBinderImplementation Instance { get; } = new AssemblyBinderImplementation(); @@ -194,16 +196,9 @@ namespace Internal.Reflection.Execution /// that this function may never be called concurrently so that we can assume that two threads /// never update the reader and scope list at the same time. /// - /// Module to register - private void RegisterModule(ModuleInfo moduleInfo) + /// Module to register + private void RegisterModule(NativeFormatModuleInfo nativeFormatModuleInfo) { - NativeFormatModuleInfo nativeFormatModuleInfo = moduleInfo as NativeFormatModuleInfo; - - if (nativeFormatModuleInfo == null) - { - return; - } - LowLevelDictionaryWithIEnumerable scopeGroups = new LowLevelDictionaryWithIEnumerable(); foreach (KeyValuePair oldGroup in _scopeGroups) { diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs index 3a60787..0fbd8f7 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Threading; + using Internal.Runtime.Augments; using Internal.Metadata.NativeFormat; @@ -322,205 +322,53 @@ namespace Internal.Runtime.TypeLoader } /// - /// Helper class that can construct an enumerator for the module handle map, possibly adjusting - /// the module order so that a given explicitly specified module goes first - this is used - /// as optimization in cases where a certain module is most likely to contain some metadata. - /// - public struct ModuleHandleEnumerable - { - /// - /// Module map to enumerate - /// - private readonly ModuleMap _moduleMap; - - /// - /// Module handle that should be enumerated first, default(IntPtr) when not used. - /// - private readonly TypeManagerHandle _preferredModuleHandle; - - /// - /// Store module map and preferred module to pass to the enumerator upon construction. - /// - /// Module map to enumerate - /// Optional module handle to enumerate first - internal ModuleHandleEnumerable(ModuleMap moduleMap, TypeManagerHandle preferredModuleHandle) - { - _moduleMap = moduleMap; - _preferredModuleHandle = preferredModuleHandle; - } - - /// - /// Create the actual module handle enumerator. - /// - public ModuleHandleEnumerator GetEnumerator() - { - return new ModuleHandleEnumerator(_moduleMap, _preferredModuleHandle); - } - } - - /// - /// Enumerator for module handles, optionally overriding module order with a given preferred - /// module to be enumerated first. - /// - public struct ModuleHandleEnumerator - { - /// - /// The underlying ModuleInfoEnumerator handles enumeration internals - /// - private ModuleInfoEnumerator _moduleInfoEnumerator; - - /// - /// Construct the underlying module info enumerator used to iterate the module map - /// - /// Module map to enumerate - /// Optional module handle to enumerate first - internal ModuleHandleEnumerator(ModuleMap moduleMap, TypeManagerHandle preferredModuleHandle) - { - _moduleInfoEnumerator = new ModuleInfoEnumerator(moduleMap, preferredModuleHandle); - } - - /// - /// Move to next element in the module map. Return true when an element is available, - /// false when the enumeration is finished. - /// - public bool MoveNext() - { - return _moduleInfoEnumerator.MoveNext(); - } - - /// - /// Return current module handle. - /// - public TypeManagerHandle Current - { - get { return _moduleInfoEnumerator.Current.Handle; } - } - } - - /// /// Utilities for manipulating module list and metadata readers. /// public sealed class ModuleList { - /// - /// Map of module addresses to module info. Every time a new module is loaded, - /// the reference gets atomically updated to a newly copied instance of the dictionary - /// to that consumers of this dictionary can look at the reference and enumerate / process it without locking, fear that the contents of the dictionary change - /// under its hands. - /// - private volatile ModuleMap _loadedModuleMap; - - internal ModuleMap GetLoadedModuleMapInternal() { return _loadedModuleMap; } + private ModuleMap _loadedModuleMap; /// - /// List of callbacks to execute when a module gets registered. - /// - private Action _moduleRegistrationCallbacks; - - /// - /// Lock used for serializing module registrations. + /// Module list is a process-wide singleton that physically lives in the TypeLoaderEnvironment instance. /// - private Lock _moduleRegistrationLock; + public static ModuleList Instance { get; } = new ModuleList(); /// /// Register initially (eagerly) loaded modules. /// internal ModuleList() { - _loadedModuleMap = new ModuleMap(new ModuleInfo[0]); - _moduleRegistrationCallbacks = default(Action); - _moduleRegistrationLock = new Lock(); + // Fetch modules that have already been registered with the runtime + int loadedModuleCount = RuntimeAugments.GetLoadedModules(null); + TypeManagerHandle[] loadedModuleHandles = new TypeManagerHandle[loadedModuleCount]; + int loadedModuleCountUpdated = RuntimeAugments.GetLoadedModules(loadedModuleHandles); + Debug.Assert(loadedModuleCount == loadedModuleCountUpdated); - RegisterNewModules(); - } + ModuleInfo[] updatedModules = new ModuleInfo[loadedModuleHandles.Length]; - /// - /// Module list is a process-wide singleton that physically lives in the TypeLoaderEnvironment instance. - /// - public static ModuleList Instance - { - get { return TypeLoaderEnvironment.Instance.ModuleList; } - } - - /// - /// Register a new callback that gets called whenever a new module gets registered. - /// The module registration happens under a global lock so that the module registration - /// callbacks are never called concurrently. - /// - /// Method to call whenever a new module is registered - public static void AddModuleRegistrationCallback(Action newModuleRegistrationCallback) - { - // Accumulate callbacks to be notified upon module registration - Instance._moduleRegistrationCallbacks += newModuleRegistrationCallback; - - // Invoke the new callback for all modules that have already been registered - foreach (ModuleInfo moduleInfo in EnumerateModules()) + for (int newModuleIndex = 0; newModuleIndex < loadedModuleHandles.Length; newModuleIndex++) { - newModuleRegistrationCallback(moduleInfo); - } - } + ModuleInfo newModuleInfo; - /// - /// Register all modules which were added (Registered) to the runtime and are not already registered with the TypeLoader. - /// - public void RegisterNewModules() - { - // prevent multiple threads from registering modules concurrently - using (LockHolder.Hold(_moduleRegistrationLock)) - { - // Fetch modules that have already been registered with the runtime - int loadedModuleCount = RuntimeAugments.GetLoadedModules(null); - TypeManagerHandle[] loadedModuleHandles = new TypeManagerHandle[loadedModuleCount]; - int loadedModuleCountUpdated = RuntimeAugments.GetLoadedModules(loadedModuleHandles); - Debug.Assert(loadedModuleCount == loadedModuleCountUpdated); - - LowLevelList newModuleHandles = new LowLevelList(loadedModuleHandles.Length); - foreach (TypeManagerHandle moduleHandle in loadedModuleHandles) + unsafe { - // Skip already registered modules. - if (_loadedModuleMap.HandleToModuleIndex.TryGetValue(moduleHandle, out _)) + byte* pBlob; + uint cbBlob; + + if (RuntimeAugments.FindBlob(loadedModuleHandles[newModuleIndex], (int)ReflectionMapBlob.EmbeddedMetadata, new IntPtr(&pBlob), new IntPtr(&cbBlob))) { - continue; + newModuleInfo = new NativeFormatModuleInfo(loadedModuleHandles[newModuleIndex], (IntPtr)pBlob, (int)cbBlob); } - - newModuleHandles.Add(moduleHandle); - } - - // Copy existing modules to new dictionary - int oldModuleCount = _loadedModuleMap.Modules.Length; - ModuleInfo[] updatedModules = new ModuleInfo[oldModuleCount + newModuleHandles.Count]; - if (oldModuleCount > 0) - { - Array.Copy(_loadedModuleMap.Modules, 0, updatedModules, 0, oldModuleCount); - } - - for (int newModuleIndex = 0; newModuleIndex < newModuleHandles.Count; newModuleIndex++) - { - ModuleInfo newModuleInfo; - - unsafe + else { - byte* pBlob; - uint cbBlob; - - if (RuntimeAugments.FindBlob(newModuleHandles[newModuleIndex], (int)ReflectionMapBlob.EmbeddedMetadata, new IntPtr(&pBlob), new IntPtr(&cbBlob))) - { - newModuleInfo = new NativeFormatModuleInfo(newModuleHandles[newModuleIndex], (IntPtr)pBlob, (int)cbBlob); - } - else - { - newModuleInfo = new ModuleInfo(newModuleHandles[newModuleIndex]); - } + newModuleInfo = new ModuleInfo(loadedModuleHandles[newModuleIndex]); } - - updatedModules[oldModuleCount + newModuleIndex] = newModuleInfo; - - _moduleRegistrationCallbacks?.Invoke(newModuleInfo); } - // Atomically update the module map - _loadedModuleMap = new ModuleMap(updatedModules); + updatedModules[newModuleIndex] = newModuleInfo; } + + _loadedModuleMap = new ModuleMap(updatedModules); } /// @@ -633,26 +481,6 @@ namespace Internal.Runtime.TypeLoader { return new NativeFormatModuleInfoEnumerable(Instance._loadedModuleMap, preferredModule); } - - /// - /// Enumerate module handles (simplified version for code that only needs the module addresses). - /// - public static ModuleHandleEnumerable Enumerate() - { - return new ModuleHandleEnumerable(Instance._loadedModuleMap, default(TypeManagerHandle)); - } - - /// - /// Enumerate module handles (simplified version for code that only needs the module addresses). - /// Specify a module that should be enumerated first - /// - this is used as an optimization in cases when a certain binary module is more probable - /// to contain a certain information. - /// - /// Handle to the module which should be enumerated first - public static ModuleHandleEnumerable Enumerate(TypeManagerHandle preferredModule) - { - return new ModuleHandleEnumerable(Instance._loadedModuleMap, preferredModule); - } } public static partial class RuntimeSignatureHelper diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs index 18d4161..79f7662 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs @@ -231,7 +231,7 @@ namespace Internal.Runtime.TypeLoader NativeParser ifaceSigParser = new NativeParser(nativeLayoutReader, entryParser.GetUnsigned()); NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); - nativeLayoutContext._module = Instance.ModuleList.GetModuleInfoByHandle(module.Handle); + nativeLayoutContext._module = ModuleList.Instance.GetModuleInfoByHandle(module.Handle); nativeLayoutContext._typeSystemContext = context; nativeLayoutContext._typeArgumentHandles = targetType.Instantiation; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs index f7b7f5b..3a2dc3b 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs @@ -30,11 +30,11 @@ namespace Internal.Runtime.TypeLoader if (signature1.StructuralEquals(signature2)) return true; - NativeFormatModuleInfo module1 = ModuleList.GetModuleInfoByHandle(new TypeManagerHandle(signature1.ModuleHandle)); + NativeFormatModuleInfo module1 = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature1.ModuleHandle)); NativeReader reader1 = GetNativeLayoutInfoReader(signature1); NativeParser parser1 = new NativeParser(reader1, signature1.NativeLayoutOffset); - NativeFormatModuleInfo module2 = ModuleList.GetModuleInfoByHandle(new TypeManagerHandle(signature2.ModuleHandle)); + NativeFormatModuleInfo module2 = ModuleList.Instance.GetModuleInfoByHandle(new TypeManagerHandle(signature2.ModuleHandle)); NativeReader reader2 = GetNativeLayoutInfoReader(signature2); NativeParser parser2 = new NativeParser(reader2, signature2.NativeLayoutOffset); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index f9dfb5b..a5d2096 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -23,7 +23,7 @@ namespace Internal.Runtime.TypeLoader { public override TypeManagerHandle GetModuleForMetadataReader(MetadataReader reader) { - return TypeLoaderEnvironment.Instance.ModuleList.GetModuleForMetadataReader(reader); + return ModuleList.Instance.GetModuleForMetadataReader(reader); } public override bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle) @@ -111,12 +111,6 @@ namespace Internal.Runtime.TypeLoader public static TypeLoaderEnvironment Instance { get; } = new TypeLoaderEnvironment(); - /// - /// List of loaded binary modules is typically used to locate / process various metadata blobs - /// and other per-module information. - /// - public readonly ModuleList ModuleList; - // Cache the NativeReader in each module to avoid looking up the NativeLayoutInfo blob each // time we call GetNativeLayoutInfoReader(). The dictionary is a thread static variable to ensure // thread safety. Using ThreadStatic instead of a lock is ok as long as the NativeReader class is @@ -130,11 +124,6 @@ namespace Internal.Runtime.TypeLoader RuntimeAugments.InitializeLookups(new Callbacks()); } - public TypeLoaderEnvironment() - { - ModuleList = new ModuleList(); - } - // To keep the synchronization simple, we execute all type loading under a global lock private Lock _typeLoaderLock = new Lock(); @@ -491,13 +480,13 @@ namespace Internal.Runtime.TypeLoader return hashCode; } - private object TryParseNativeSignatureWorker(TypeSystemContext typeSystemContext, TypeManagerHandle moduleHandle, ref NativeParser parser, RuntimeTypeHandle[] typeGenericArgumentHandles, RuntimeTypeHandle[] methodGenericArgumentHandles, bool isMethodSignature) + private static object TryParseNativeSignatureWorker(TypeSystemContext typeSystemContext, TypeManagerHandle moduleHandle, ref NativeParser parser, RuntimeTypeHandle[] typeGenericArgumentHandles, RuntimeTypeHandle[] methodGenericArgumentHandles, bool isMethodSignature) { Instantiation typeGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(typeGenericArgumentHandles ?? Array.Empty()); Instantiation methodGenericArguments = typeSystemContext.ResolveRuntimeTypeHandles(methodGenericArgumentHandles ?? Array.Empty()); NativeLayoutInfoLoadContext nativeLayoutContext = new NativeLayoutInfoLoadContext(); - nativeLayoutContext._module = ModuleList.GetModuleInfoByHandle(moduleHandle); + nativeLayoutContext._module = ModuleList.Instance.GetModuleInfoByHandle(moduleHandle); nativeLayoutContext._typeSystemContext = typeSystemContext; nativeLayoutContext._typeArgumentHandles = typeGenericArguments; nativeLayoutContext._methodArgumentHandles = methodGenericArguments; -- 2.7.4