Skip to content

Commit 9ab251b

Browse files
authored
Rework string table minimization (#56)
1 parent 33d5489 commit 9ab251b

File tree

5 files changed

+67
-7
lines changed

5 files changed

+67
-7
lines changed

source/MetadataProcessor.Core/Tables/nanoByteCodeTable.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public sealed class nanoByteCodeTable : InanoTable
3232
/// <summary>
3333
/// Temporary string table for code generators used during initial load.
3434
/// </summary>
35-
private readonly nanoStringTable _fakeStringTable = new nanoStringTable();
35+
private readonly nanoStringTable _fakeStringTable;
3636

3737
/// <summary>
3838
/// Assembly tables context - contains all tables used for building target assembly.
@@ -54,6 +54,8 @@ public nanoByteCodeTable(
5454
nanoTablesContext context)
5555
{
5656
_context = context;
57+
58+
_fakeStringTable = new nanoStringTable(_context);
5759
}
5860

5961
/// <summary>

source/MetadataProcessor.Core/Tables/nanoStringTable.cs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,30 @@ public IEnumerable<string> Sort(
4848
/// </summary>
4949
private ushort _lastAvailableId;
5050

51+
private ushort _lastPreAllocatedId;
52+
53+
/// <summary>
54+
/// Assembly tables context - contains all tables used for building target assembly.
55+
/// </summary>
56+
private readonly nanoTablesContext _context;
57+
58+
/// <summary>
59+
/// Last pre-allocated string identifier.
60+
/// </summary>
61+
public ushort LastPreAllocatedId { get => _lastPreAllocatedId; }
62+
5163
/// <summary>
5264
/// Creates new instance of <see cref="nanoStringTable"/> object.
5365
/// </summary>
5466
public nanoStringTable(
67+
nanoTablesContext context,
5568
ICustomStringSorter stringSorter = null)
5669
{
5770
GetOrCreateStringId(string.Empty); // First item in string table always empty string
5871
_stringSorter = stringSorter ?? new EmptyStringSorter();
59-
}
6072

61-
73+
_context = context;
74+
}
6275

6376
/// <summary>
6477
/// Gets existing or creates new string reference identifier related to passed string value.
@@ -164,6 +177,46 @@ public void RemoveUnusedItems(HashSet<MetadataToken> items)
164177
// First item in string table always empty string
165178
GetOrCreateStringId(string.Empty);
166179

180+
// Pre-allocate strings from some tables
181+
_context.AssemblyReferenceTable.AllocateStrings();
182+
_context.TypeReferencesTable.AllocateStrings();
183+
184+
185+
var memberReferences = _context.AssemblyDefinition.MainModule.GetMemberReferences();
186+
List<MemberReference> memberReferencesInUse = new List<MemberReference>();
187+
188+
foreach (var item in memberReferences)
189+
{
190+
var memberRef = _context.TypeReferencesTable.Items.FirstOrDefault(m => m.FullName.Contains(item.DeclaringType.FullName));
191+
if (memberRef != null)
192+
{
193+
memberReferencesInUse.Add(item);
194+
}
195+
}
196+
197+
foreach (var item in memberReferencesInUse)
198+
{
199+
GetOrCreateStringId(item.Name);
200+
}
201+
202+
foreach (var item in _context.TypeDefinitionTable.Items)
203+
{
204+
GetOrCreateStringId(item.Namespace);
205+
GetOrCreateStringId(item.Name);
206+
207+
foreach (var f in item.Fields)
208+
{
209+
GetOrCreateStringId(f.Name);
210+
}
211+
212+
foreach (var m in item.Methods)
213+
{
214+
GetOrCreateStringId(m.Name);
215+
}
216+
}
217+
218+
_lastPreAllocatedId = _idsByStrings.Last().Value;
219+
167220
// fill in the dictionary with the used strings
168221
foreach (var s in usedStrings)
169222
{

source/MetadataProcessor.Core/Tables/nanoTablesContext.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ public nanoTablesContext(
159159
// Strings and signatures
160160

161161
SignaturesTable = new nanoSignaturesTable(this);
162-
StringTable = new nanoStringTable(stringSorter);
162+
StringTable = new nanoStringTable(
163+
this,
164+
stringSorter);
163165

164166
// Byte code table
165167
ByteCodeTable = new nanoByteCodeTable(this);

source/MetadataProcessor.Core/nanoDumperGenerator.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ private void DumpCustomAttributes(DumpAllTable dumpTable)
8585

8686
private void DumpUserStrings(DumpAllTable dumpTable)
8787
{
88-
foreach (var s in _tablesContext.StringTable.GetItems().OrderBy(i => i.Value))
88+
// start at 1, because 0 is the empty string entry
89+
int tokenId = 1;
90+
91+
foreach (var s in _tablesContext.StringTable.GetItems().OrderBy(i => i.Value).Where(i => i.Value > _tablesContext.StringTable.LastPreAllocatedId))
8992
{
9093
// don't output the empty string
9194
if(s.Value == 0)
@@ -94,7 +97,7 @@ private void DumpUserStrings(DumpAllTable dumpTable)
9497
}
9598

9699
// fake the metadata token from the ID
97-
var stringMetadataToken = new MetadataToken(TokenType.String, s.Value);
100+
var stringMetadataToken = new MetadataToken(TokenType.String, tokenId++);
98101

99102
dumpTable.UserStrings.Add(
100103
new UserString()

source/version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3-
"version": "2.18.0",
3+
"version": "2.19.0",
44
"release": {
55
"branchName" : "release-v{version}",
66
"versionIncrement" : "minor",

0 commit comments

Comments
 (0)