Skip to content

Commit d99cce3

Browse files
authored
Improvements in assembly minimization algorithm (#32)
1 parent 5a9477b commit d99cce3

File tree

11 files changed

+93
-85
lines changed

11 files changed

+93
-85
lines changed

source/MetadataProcessor.Console/MetadataProcessor.Console.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
</ItemGroup>
5858
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
5959
<ItemGroup>
60+
<None Include="app.config" />
6061
<None Include="packages.config" />
6162
</ItemGroup>
6263
<ItemGroup>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<runtime>
4+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5+
<dependentAssembly>
6+
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
7+
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
8+
</dependentAssembly>
9+
<dependentAssembly>
10+
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
11+
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
12+
</dependentAssembly>
13+
<dependentAssembly>
14+
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
15+
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
16+
</dependentAssembly>
17+
<dependentAssembly>
18+
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
19+
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
20+
</dependentAssembly>
21+
<dependentAssembly>
22+
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
23+
<bindingRedirect oldVersion="0.0.0.0-1.2.5.0" newVersion="1.2.5.0" />
24+
</dependentAssembly>
25+
</assemblyBinding>
26+
</runtime>
27+
</configuration>

source/MetadataProcessor.Core/MetadataProcessor.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
<Compile Include="Utility\NativeMethodsCrc.cs" />
125125
</ItemGroup>
126126
<ItemGroup>
127+
<None Include="app.config" />
127128
<None Include="key.snk" />
128129
<None Include="packages.config" />
129130
<Compile Include="SkeletonGenerator\SkeletonTemplates.cs" />

source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,9 @@ public ushort GetMethodRva(
111111
public void Write(
112112
nanoBinaryWriter writer)
113113
{
114-
if (_context.UsedElements != null)
114+
foreach (var method in _methods)
115115
{
116-
foreach (var method in _methods.Where(item => _context.UsedElements.Contains(item.MetadataToken)))
117-
{
118-
writer.WriteBytes(CreateByteCode(method, writer));
119-
}
120-
}
121-
else
122-
{
123-
foreach (var method in _methods)
124-
{
125-
writer.WriteBytes(CreateByteCode(method, writer));
126-
}
116+
writer.WriteBytes(CreateByteCode(method, writer));
127117
}
128118
}
129119

source/MetadataProcessor.Core/Tables/nanoReferenceTableBase.cs

Lines changed: 23 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public abstract class nanoReferenceTableBase<T> : InanoTable
2121
/// <summary>
2222
/// Lookup table for finding item ID by item value.
2323
/// </summary>
24-
private readonly Dictionary<T, ushort> _idsByItemsDictionary;
24+
private Dictionary<T, ushort> _idsByItemsDictionary;
2525

2626
/// <summary>
2727
/// Assembly tables context - contains all tables used for building target assembly.
@@ -31,10 +31,12 @@ public abstract class nanoReferenceTableBase<T> : InanoTable
3131
/// <summary>
3232
/// Lookup table for finding item ID by item value.
3333
/// </summary>
34-
protected readonly IEnumerable<T> _items;
34+
protected IEnumerable<T> _items;
3535

3636
public IEnumerable<T> Items => _items;
3737

38+
private readonly IEqualityComparer<T> _comparer;
39+
3840
/// <summary>
3941
/// Creates new instance of <see cref="nanoReferenceTableBase{T}"/> object.
4042
/// </summary>
@@ -55,47 +57,26 @@ protected nanoReferenceTableBase(
5557

5658
_context = context;
5759

60+
_comparer = comparer;
61+
5862
_items = nanoTableItems;
5963
}
6064

6165
/// <inheritdoc/>
6266
public void Write(
6367
nanoBinaryWriter writer)
64-
{
65-
if (_context.UsedElements != null)
66-
{
67-
foreach (var item in _idsByItemsDictionary
68-
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
69-
.OrderBy(item => item.Value)
70-
.Select(item => item.Key))
71-
{
72-
WriteSingleItem(writer, item);
73-
}
74-
}
75-
else
76-
{
77-
foreach (var item in _idsByItemsDictionary
78-
.OrderBy(item => item.Value)
79-
.Select(item => item.Key))
80-
{
81-
WriteSingleItem(writer, item);
82-
}
83-
}
84-
}
85-
86-
public void ForEachItems(Action<uint, T> action)
8768
{
8869
foreach (var item in _idsByItemsDictionary
89-
.OrderBy(item => item.Value))
70+
.OrderBy(item => item.Value)
71+
.Select(item => item.Key))
9072
{
91-
action(item.Value, item.Key);
73+
WriteSingleItem(writer, item);
9274
}
9375
}
9476

95-
public void ForEachItemInUse(Action<uint, T> action)
77+
public void ForEachItems(Action<uint, T> action)
9678
{
9779
foreach (var item in _idsByItemsDictionary
98-
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
9980
.OrderBy(item => item.Value))
10081
{
10182
action(item.Value, item.Key);
@@ -114,16 +95,6 @@ public void AllocateStrings()
11495
AllocateSingleItemStrings(item);
11596
}
11697
}
117-
public void AllocateStringsInUse()
118-
{
119-
foreach (var item in _idsByItemsDictionary
120-
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken))
121-
.OrderBy(item => item.Value)
122-
.Select(item => item.Key))
123-
{
124-
AllocateSingleItemStrings(item);
125-
}
126-
}
12798

12899
/// <summary>
129100
/// Writes string reference ID related to passed string value into output stream.
@@ -179,28 +150,25 @@ protected abstract void WriteSingleItem(
179150
nanoBinaryWriter writer,
180151
T item);
181152

182-
public IEnumerable<T> GetUsedItems()
153+
/// <summary>
154+
/// Remove unused items from table.
155+
/// </summary>
156+
public void RemoveUnusedItems(HashSet<MetadataToken> set)
183157
{
158+
// build a collection of the current items that are present in the used items set
184159
List<T> usedItems = new List<T>();
185160

186-
if (_context.UsedElements != null)
187-
{
188-
189-
foreach (var item in _idsByItemsDictionary
190-
.Where(item => _context.UsedElements.Contains(((IMetadataTokenProvider)item.Key).MetadataToken)))
191-
{
192-
usedItems.Add(item.Key);
193-
}
194-
}
195-
else
161+
foreach (var item in _idsByItemsDictionary
162+
.Where(item => set.Contains(((IMetadataTokenProvider)item.Key).MetadataToken)))
196163
{
197-
foreach (var item in _idsByItemsDictionary)
198-
{
199-
usedItems.Add(item.Key);
200-
}
164+
usedItems.Add(item.Key);
201165
}
202166

203-
return usedItems;
167+
// re-create the items dictionary with the used items only
168+
_idsByItemsDictionary = usedItems
169+
.Select((reference, index) => new { reference, index })
170+
.ToDictionary(item => item.reference, item => (ushort)item.index,
171+
_comparer);
204172
}
205173
}
206174
}

source/MetadataProcessor.Core/Tables/nanoTablesContext.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,6 @@ public ushort GetMethodReferenceId(
242242

243243
public List<string> ClassNamesToExclude { get; private set; }
244244

245-
public HashSet<MetadataToken> UsedElements { get; internal set; }
246-
247245
private IEnumerable<Tuple<CustomAttribute, ushort>> GetAttributes(
248246
IEnumerable<ICustomAttributeProvider> types,
249247
bool applyAttributesCompression)
@@ -433,12 +431,10 @@ internal void ResetStringsTable()
433431

434432
var typeReferencesNames = new HashSet<string>(
435433
typeReferences
436-
.Where(item => UsedElements.Contains(((IMetadataTokenProvider)item).MetadataToken))
437434
.Select(item => item.FullName),
438435
StringComparer.Ordinal);
439436

440437
var memberReferences = mainModule.GetMemberReferences()
441-
.Where(item => UsedElements.Contains(((IMetadataTokenProvider)item).MetadataToken))
442438
.Where(item => typeReferencesNames.Contains(item.DeclaringType.FullName))
443439
.ToList();
444440

source/MetadataProcessor.Core/Utility/NativeMethodsCrc.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ internal static string GetnanoClrTypeName(TypeReference parameterType)
137137

138138
internal void UpdateCrc(nanoTypeDefinitionTable typeDefinitionTable)
139139
{
140-
foreach (var c in typeDefinitionTable.TypeDefinitions)
140+
foreach (var c in typeDefinitionTable.Items)
141141
{
142142
if (c.IncludeInStub() && !IsClassToExclude(c))
143143
{

source/MetadataProcessor.Core/Utility/nanoPdbxFileWriter.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,7 @@ public void Write(
3535

3636
writer.WriteStartElement("Classes");
3737

38-
if (_context.UsedElements != null)
39-
{
40-
_context.TypeDefinitionTable.ForEachItemInUse((token, item) => WriteClassInfo(writer, token, item));
41-
}
42-
else
43-
{
44-
_context.TypeDefinitionTable.ForEachItems((token, item) => WriteClassInfo(writer, token, item));
45-
}
38+
_context.TypeDefinitionTable.ForEachItems((token, item) => WriteClassInfo(writer, token, item));
4639

4740
writer.WriteEndDocument();
4841
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<runtime>
4+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5+
<dependentAssembly>
6+
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
7+
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
8+
</dependentAssembly>
9+
<dependentAssembly>
10+
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
11+
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
12+
</dependentAssembly>
13+
<dependentAssembly>
14+
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
15+
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
16+
</dependentAssembly>
17+
<dependentAssembly>
18+
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
19+
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
20+
</dependentAssembly>
21+
<dependentAssembly>
22+
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
23+
<bindingRedirect oldVersion="0.0.0.0-1.2.5.0" newVersion="1.2.5.0" />
24+
</dependentAssembly>
25+
</assemblyBinding>
26+
</runtime>
27+
</configuration>

source/MetadataProcessor.Core/nanoAssemblyBuilder.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,15 @@ public void Minimize()
151151
}
152152
}
153153

154-
_tablesContext.UsedElements = set;
155-
156-
// need to reset several tables
154+
// need to reset several tables so they are recreated only with the used items
157155
_tablesContext.ResetStringsTable();
156+
_tablesContext.AssemblyReferenceTable.RemoveUnusedItems(set);
157+
_tablesContext.FieldsTable.RemoveUnusedItems(set);
158+
_tablesContext.FieldReferencesTable.RemoveUnusedItems(set);
159+
_tablesContext.MethodDefinitionTable.RemoveUnusedItems(set);
160+
_tablesContext.MethodReferencesTable.RemoveUnusedItems(set);
161+
_tablesContext.TypeDefinitionTable.RemoveUnusedItems(set);
162+
_tablesContext.TypeReferencesTable.RemoveUnusedItems(set);
158163
_tablesContext.TypeDefinitionTable.ResetByteCodeOffsets();
159164
_tablesContext.ResetByteCodeTable();
160165
_tablesContext.ResetSignaturesTable();

0 commit comments

Comments
 (0)