1010using Internal . NativeFormat ;
1111using Internal . Reflection . Core . Execution ;
1212using Internal . Runtime ;
13- using Internal . Runtime . Augments ;
1413using Internal . Runtime . TypeLoader ;
1514
1615namespace Internal . Reflection . Execution
@@ -22,53 +21,65 @@ internal sealed partial class ExecutionEnvironmentImplementation : ExecutionEnvi
2221 {
2322 public sealed override ManifestResourceInfo GetManifestResourceInfo ( Assembly assembly , string resourceName )
2423 {
25- LowLevelList < ResourceInfo > resourceInfos = GetExtractedResources ( assembly ) ;
26- for ( int i = 0 ; i < resourceInfos . Count ; i ++ )
24+ if ( FindResourceWithName ( assembly , resourceName ) . Module != null )
2725 {
28- if ( resourceName == resourceInfos [ i ] . Name )
29- {
30- return new ManifestResourceInfo ( null , null , ResourceLocation . Embedded | ResourceLocation . ContainedInManifestFile ) ;
31- }
26+ return new ManifestResourceInfo ( null , null , ResourceLocation . Embedded | ResourceLocation . ContainedInManifestFile ) ;
3227 }
28+
3329 return null ;
3430 }
3531
3632 public sealed override string [ ] GetManifestResourceNames ( Assembly assembly )
3733 {
38- LowLevelList < ResourceInfo > resourceInfos = GetExtractedResources ( assembly ) ;
39- string [ ] names = new string [ resourceInfos . Count ] ;
40- for ( int i = 0 ; i < resourceInfos . Count ; i ++ )
34+ string assemblyName = assembly . GetName ( ) . FullName ;
35+ int assemblyNameHash = TypeHashingAlgorithms . ComputeNameHashCode ( assemblyName ) ;
36+ ArrayBuilder < string > arrayBuilder = default ;
37+
38+ foreach ( NativeFormatModuleInfo module in ModuleList . EnumerateModules ( ) )
4139 {
42- names [ i ] = resourceInfos [ i ] . Name ;
40+ if ( ! TryGetNativeReaderForBlob ( module , ReflectionMapBlob . BlobIdResourceIndex , out NativeReader reader ) )
41+ {
42+ continue ;
43+ }
44+ NativeParser indexParser = new NativeParser ( reader , 0 ) ;
45+ NativeHashtable indexHashTable = new NativeHashtable ( indexParser ) ;
46+
47+ var lookup = indexHashTable . Lookup ( assemblyNameHash ) ;
48+ NativeParser entryParser ;
49+ while ( ! ( entryParser = lookup . GetNext ( ) ) . IsNull )
50+ {
51+ if ( entryParser . StringEquals ( assemblyName ) )
52+ {
53+ entryParser . SkipString ( ) ; // assemblyName
54+ arrayBuilder . Add ( entryParser . GetString ( ) ) ;
55+ }
56+ else
57+ {
58+ entryParser . SkipString ( ) ; // assemblyName
59+ entryParser . SkipString ( ) ; // resourceName
60+ }
61+ entryParser . SkipInteger ( ) ; // offset
62+ entryParser . SkipInteger ( ) ; // length
63+ }
4364 }
44- return names ;
65+
66+ return arrayBuilder . ToArray ( ) ;
4567 }
4668
4769 public sealed override Stream GetManifestResourceStream ( Assembly assembly , string name )
4870 {
49- ArgumentNullException . ThrowIfNull ( name ) ;
50-
51- // This was most likely an embedded resource which the toolchain should have embedded
52- // into an assembly.
53- LowLevelList < ResourceInfo > resourceInfos = GetExtractedResources ( assembly ) ;
54- for ( int i = 0 ; i < resourceInfos . Count ; i ++ )
71+ ResourceInfo resourceInfo = FindResourceWithName ( assembly , name ) ;
72+ if ( resourceInfo . Module != null )
5573 {
56- ResourceInfo resourceInfo = resourceInfos [ i ] ;
57- if ( name == resourceInfo . Name )
58- {
59- return ReadResourceFromBlob ( resourceInfo ) ;
60- }
74+ return ReadResourceFromBlob ( resourceInfo ) ;
6175 }
6276
6377 return null ;
6478 }
6579
6680 private static unsafe UnmanagedMemoryStream ReadResourceFromBlob ( ResourceInfo resourceInfo )
6781 {
68- byte * pBlob ;
69- uint cbBlob ;
70-
71- if ( ! resourceInfo . Module . TryFindBlob ( ( int ) ReflectionMapBlob . BlobIdResourceData , out pBlob , out cbBlob ) )
82+ if ( ! resourceInfo . Module . TryFindBlob ( ( int ) ReflectionMapBlob . BlobIdResourceData , out byte * pBlob , out uint cbBlob ) )
7283 {
7384 throw new BadImageFormatException ( ) ;
7485 }
@@ -78,85 +89,57 @@ private static unsafe UnmanagedMemoryStream ReadResourceFromBlob(ResourceInfo re
7889 return new UnmanagedMemoryStream ( pBlob + resourceInfo . Index , resourceInfo . Length ) ;
7990 }
8091
81- private static LowLevelList < ResourceInfo > GetExtractedResources ( Assembly assembly )
92+ private static ResourceInfo FindResourceWithName ( Assembly assembly , string resourceName )
8293 {
83- LowLevelDictionary < string , LowLevelList < ResourceInfo > > extractedResourceDictionary = ExtractedResourceDictionary ;
8494 string assemblyName = assembly . GetName ( ) . FullName ;
85- LowLevelList < ResourceInfo > resourceInfos ;
86- if ( ! extractedResourceDictionary . TryGetValue ( assemblyName , out resourceInfos ) )
87- return new LowLevelList < ResourceInfo > ( ) ;
88- return resourceInfos ;
89- }
95+ int assemblyNameHash = TypeHashingAlgorithms . ComputeNameHashCode ( assemblyName ) ;
9096
91- private static LowLevelDictionary < string , LowLevelList < ResourceInfo > > ExtractedResourceDictionary
92- {
93- get
97+ foreach ( NativeFormatModuleInfo module in ModuleList . EnumerateModules ( ) )
9498 {
95- if ( s_extractedResourceDictionary == null )
99+ if ( ! TryGetNativeReaderForBlob ( module , ReflectionMapBlob . BlobIdResourceIndex , out NativeReader reader ) )
96100 {
97- // Lazily create the extracted resource dictionary. If two threads race here, we may construct two dictionaries
98- // and overwrite one - this is ok since the dictionaries are read-only once constructed and they contain the identical data.
99-
100- LowLevelDictionary < string , LowLevelList < ResourceInfo > > dict = new LowLevelDictionary < string , LowLevelList < ResourceInfo > > ( ) ;
101+ continue ;
102+ }
103+ NativeParser indexParser = new NativeParser ( reader , 0 ) ;
104+ NativeHashtable indexHashTable = new NativeHashtable ( indexParser ) ;
101105
102- foreach ( NativeFormatModuleInfo module in ModuleList . EnumerateModules ( ) )
106+ var lookup = indexHashTable . Lookup ( assemblyNameHash ) ;
107+ NativeParser entryParser ;
108+ while ( ! ( entryParser = lookup . GetNext ( ) ) . IsNull )
109+ {
110+ if ( entryParser . StringEquals ( assemblyName ) )
103111 {
104- NativeReader reader ;
105- if ( ! TryGetNativeReaderForBlob ( module , ReflectionMapBlob . BlobIdResourceIndex , out reader ) )
106- {
107- continue ;
108- }
109- NativeParser indexParser = new NativeParser ( reader , 0 ) ;
110- NativeHashtable indexHashTable = new NativeHashtable ( indexParser ) ;
111-
112- var entryEnumerator = indexHashTable . EnumerateAllEntries ( ) ;
113- NativeParser entryParser ;
114- while ( ! ( entryParser = entryEnumerator . GetNext ( ) ) . IsNull )
112+ entryParser . SkipString ( ) ; // assemblyName
113+ if ( entryParser . StringEquals ( resourceName ) )
115114 {
116- string assemblyName = entryParser . GetString ( ) ;
117- string resourceName = entryParser . GetString ( ) ;
115+ entryParser . SkipString ( ) ; // resourceName
118116 int resourceOffset = ( int ) entryParser . GetUnsigned ( ) ;
119117 int resourceLength = ( int ) entryParser . GetUnsigned ( ) ;
120-
121- ResourceInfo resourceInfo = new ResourceInfo ( resourceName , resourceOffset , resourceLength , module ) ;
122-
123- LowLevelList < ResourceInfo > assemblyResources ;
124- if ( ! dict . TryGetValue ( assemblyName , out assemblyResources ) )
125- {
126- assemblyResources = new LowLevelList < ResourceInfo > ( ) ;
127- dict [ assemblyName ] = assemblyResources ;
128- }
129-
130- assemblyResources . Add ( resourceInfo ) ;
118+ return new ResourceInfo ( resourceOffset , resourceLength , module ) ;
131119 }
132120 }
133-
134- s_extractedResourceDictionary = dict ;
121+ else
122+ {
123+ entryParser . SkipString ( ) ; // assemblyName
124+ }
125+ entryParser . SkipString ( ) ; // resourceName
126+ entryParser . SkipInteger ( ) ; // offset
127+ entryParser . SkipInteger ( ) ; // length
135128 }
136- return s_extractedResourceDictionary ;
137129 }
138- }
139130
140- /// <summary>
141- /// This dictionary gets us from assembly + resource name to the offset of a resource
142- /// inside the resource data blob
143- ///
144- /// The dictionary's key is a Fusion-style assembly name.
145- /// The dictionary's value is a list of (resourcename,index) tuples.
146- /// </summary>
147- private static volatile LowLevelDictionary < string , LowLevelList < ResourceInfo > > s_extractedResourceDictionary ;
131+ return default ;
132+ }
148133
149134 private struct ResourceInfo
150135 {
151- public ResourceInfo ( string name , int index , int length , NativeFormatModuleInfo module )
136+ public ResourceInfo ( int index , int length , NativeFormatModuleInfo module )
152137 {
153- Name = name ;
154138 Index = index ;
155139 Length = length ;
156140 Module = module ;
157141 }
158142
159- public string Name { get ; }
160143 public int Index { get ; }
161144 public int Length { get ; }
162145 public NativeFormatModuleInfo Module { get ; }
0 commit comments