-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Further clean up usages of LowLevelList<T> #109114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d465850
a672cdf
0bfd0cb
46546e6
8d45b8d
b1aa7db
4bc86fe
2aa0f67
e561f32
cbfe20c
9bcd4dc
5686096
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,7 +51,7 @@ public override int GetHashCode() | |
|
|
||
| private static uint s_genericFunctionPointerNextIndex; | ||
| private const uint c_genericDictionaryChunkSize = 1024; | ||
| private static LowLevelList<IntPtr> s_genericFunctionPointerCollection = new LowLevelList<IntPtr>(); | ||
| private static readonly List<IntPtr> s_genericFunctionPointerCollection = new List<IntPtr>(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean there will be memory leak per function pointer, instead of per method instantiation? This would become unbounded instead of bounded. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| private static LowLevelDictionary<GenericMethodDescriptorInfo, uint> s_genericFunctionPointerDictionary = new LowLevelDictionary<GenericMethodDescriptorInfo, uint>(); | ||
|
|
||
| public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunctionPointer, IntPtr instantiationArgument) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,7 @@ internal sealed partial class ExecutionEnvironmentImplementation : ExecutionEnvi | |
| { | ||
| public sealed override ManifestResourceInfo GetManifestResourceInfo(Assembly assembly, string resourceName) | ||
| { | ||
| LowLevelList<ResourceInfo> resourceInfos = GetExtractedResources(assembly); | ||
| List<ResourceInfo> resourceInfos = GetExtractedResources(assembly); | ||
| for (int i = 0; i < resourceInfos.Count; i++) | ||
| { | ||
| if (resourceName == resourceInfos[i].Name) | ||
|
|
@@ -35,7 +35,7 @@ public sealed override ManifestResourceInfo GetManifestResourceInfo(Assembly ass | |
|
|
||
| public sealed override string[] GetManifestResourceNames(Assembly assembly) | ||
| { | ||
| LowLevelList<ResourceInfo> resourceInfos = GetExtractedResources(assembly); | ||
| List<ResourceInfo> resourceInfos = GetExtractedResources(assembly); | ||
| string[] names = new string[resourceInfos.Count]; | ||
| for (int i = 0; i < resourceInfos.Count; i++) | ||
| { | ||
|
|
@@ -50,7 +50,7 @@ public sealed override Stream GetManifestResourceStream(Assembly assembly, strin | |
|
|
||
| // This was most likely an embedded resource which the toolchain should have embedded | ||
| // into an assembly. | ||
| LowLevelList<ResourceInfo> resourceInfos = GetExtractedResources(assembly); | ||
| List<ResourceInfo> resourceInfos = GetExtractedResources(assembly); | ||
| for (int i = 0; i < resourceInfos.Count; i++) | ||
| { | ||
| ResourceInfo resourceInfo = resourceInfos[i]; | ||
|
|
@@ -78,17 +78,17 @@ private static unsafe UnmanagedMemoryStream ReadResourceFromBlob(ResourceInfo re | |
| return new UnmanagedMemoryStream(pBlob + resourceInfo.Index, resourceInfo.Length); | ||
| } | ||
|
|
||
| private static LowLevelList<ResourceInfo> GetExtractedResources(Assembly assembly) | ||
| private static List<ResourceInfo> GetExtractedResources(Assembly assembly) | ||
| { | ||
| LowLevelDictionary<string, LowLevelList<ResourceInfo>> extractedResourceDictionary = ExtractedResourceDictionary; | ||
| Dictionary<string, List<ResourceInfo>> extractedResourceDictionary = ExtractedResourceDictionary; | ||
| string assemblyName = assembly.GetName().FullName; | ||
| LowLevelList<ResourceInfo> resourceInfos; | ||
| List<ResourceInfo> resourceInfos; | ||
| if (!extractedResourceDictionary.TryGetValue(assemblyName, out resourceInfos)) | ||
| return new LowLevelList<ResourceInfo>(); | ||
| return new List<ResourceInfo>(); | ||
| return resourceInfos; | ||
| } | ||
|
|
||
| private static LowLevelDictionary<string, LowLevelList<ResourceInfo>> ExtractedResourceDictionary | ||
| private static Dictionary<string, List<ResourceInfo>> ExtractedResourceDictionary | ||
| { | ||
| get | ||
| { | ||
|
|
@@ -97,7 +97,7 @@ private static LowLevelDictionary<string, LowLevelList<ResourceInfo>> ExtractedR | |
| // Lazily create the extracted resource dictionary. If two threads race here, we may construct two dictionaries | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the question to ask here is whether we need to create this global cache in the first place. |
||
| // and overwrite one - this is ok since the dictionaries are read-only once constructed and they contain the identical data. | ||
|
|
||
| LowLevelDictionary<string, LowLevelList<ResourceInfo>> dict = new LowLevelDictionary<string, LowLevelList<ResourceInfo>>(); | ||
| Dictionary<string, List<ResourceInfo>> dict = new Dictionary<string, List<ResourceInfo>>(); | ||
|
|
||
| foreach (NativeFormatModuleInfo module in ModuleList.EnumerateModules()) | ||
| { | ||
|
|
@@ -120,10 +120,10 @@ private static LowLevelDictionary<string, LowLevelList<ResourceInfo>> ExtractedR | |
|
|
||
| ResourceInfo resourceInfo = new ResourceInfo(resourceName, resourceOffset, resourceLength, module); | ||
|
|
||
| LowLevelList<ResourceInfo> assemblyResources; | ||
| List<ResourceInfo> assemblyResources; | ||
| if (!dict.TryGetValue(assemblyName, out assemblyResources)) | ||
| { | ||
| assemblyResources = new LowLevelList<ResourceInfo>(); | ||
| assemblyResources = new List<ResourceInfo>(); | ||
| dict[assemblyName] = assemblyResources; | ||
| } | ||
|
|
||
|
|
@@ -144,7 +144,7 @@ private static LowLevelDictionary<string, LowLevelList<ResourceInfo>> ExtractedR | |
| /// The dictionary's key is a Fusion-style assembly name. | ||
| /// The dictionary's value is a list of (resourcename,index) tuples. | ||
| /// </summary> | ||
| private static volatile LowLevelDictionary<string, LowLevelList<ResourceInfo>> s_extractedResourceDictionary; | ||
| private static volatile Dictionary<string, List<ResourceInfo>> s_extractedResourceDictionary; | ||
|
|
||
| private struct ResourceInfo | ||
| { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the type be moved under TypeLoader since it's only required for it?
Additional question: is
ForceDictionaryLookupsonly applicable for reference types because of generic sharing, or also applicable for value types?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is very likely that there is code in CoreLib that is used by the TypeLoader indirectly that would need to be annotated with this attribute if we ever resurrected this (#85184 (comment)).
I think it would be ok to delete ForceDictionaryLookups and its few remaining uses. It is likely heavily bitrotten.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, in this PR I was using
Array.Resizewhich is generic. It seems that the real foreseeing solution is to limit TypeLoader usage of CoreLib, according to the linked discussion. It also means that TypeLoader needs its specialized collection. If we resurrected the generic lookup work, is it expected to use the attribute, or just do some specialized handling for TypeLoader?The original question is that, would there be any place else (not involved with TypeLoader) unable to use the CoreLib collection? I assume no.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per #85184 (comment), if we ever resurrected the lazy generic lookup work, we would need likely ended up with TypeLoader in its own partition that does not perform the lazy generic lookups. It would be very large refactoring.