Skip to content

Commit

Permalink
Merge pull request #316 from Washi1337/feature/collection-capacities
Browse files Browse the repository at this point in the history
Add and use collection Capacity properties
  • Loading branch information
Washi1337 authored May 26, 2022
2 parents 930ef22 + 80f5b35 commit 036c408
Show file tree
Hide file tree
Showing 25 changed files with 322 additions and 96 deletions.
24 changes: 24 additions & 0 deletions src/AsmResolver.DotNet/Builder/DotNetDirectoryBuffer.MemberTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ public void DefineTypes(IEnumerable<TypeDefinition> types)
var typeDefTable = Metadata.TablesStream.GetTable<TypeDefinitionRow>(TableIndex.TypeDef);
var nestedClassTable = Metadata.TablesStream.GetSortedTable<TypeDefinition, NestedClassRow>(TableIndex.NestedClass);

if (types is ICollection<TypeDefinition> collection)
typeDefTable.EnsureCapacity(typeDefTable.Count + collection.Count);

foreach (var type in types)
{
// At this point, we might not have added all type defs/refs/specs yet, so we cannot determine
Expand Down Expand Up @@ -177,6 +180,8 @@ public void DefineTypes(IEnumerable<TypeDefinition> types)
public void DefineFields(IEnumerable<FieldDefinition> fields)
{
var table = Metadata.TablesStream.GetTable<FieldDefinitionRow>(TableIndex.Field);
if (fields is ICollection<FieldDefinition> collection)
table.EnsureCapacity(table.Count + collection.Count);

foreach (var field in fields)
{
Expand All @@ -197,6 +202,8 @@ public void DefineFields(IEnumerable<FieldDefinition> fields)
public void DefineMethods(IEnumerable<MethodDefinition> methods)
{
var table = Metadata.TablesStream.GetTable<MethodDefinitionRow>(TableIndex.Method);
if (methods is ICollection<MethodDefinition> collection)
table.EnsureCapacity(table.Count + collection.Count);

foreach (var method in methods)
{
Expand Down Expand Up @@ -227,6 +234,8 @@ public void DefineMethods(IEnumerable<MethodDefinition> methods)
public void DefineParameters(IEnumerable<ParameterDefinition> parameters)
{
var table = Metadata.TablesStream.GetTable<ParameterDefinitionRow>(TableIndex.Param);
if (parameters is ICollection<ParameterDefinition> collection)
table.EnsureCapacity(table.Count + collection.Count);

foreach (var parameter in parameters)
{
Expand All @@ -247,6 +256,8 @@ public void DefineParameters(IEnumerable<ParameterDefinition> parameters)
public void DefineProperties(IEnumerable<PropertyDefinition> properties)
{
var table = Metadata.TablesStream.GetTable<PropertyDefinitionRow>(TableIndex.Property);
if (properties is ICollection<PropertyDefinition> collection)
table.EnsureCapacity(table.Count + collection.Count);

foreach (var property in properties)
{
Expand All @@ -267,6 +278,8 @@ public void DefineProperties(IEnumerable<PropertyDefinition> properties)
public void DefineEvents(IEnumerable<EventDefinition> events)
{
var table = Metadata.TablesStream.GetTable<EventDefinitionRow>(TableIndex.Event);
if (events is ICollection<EventDefinition> collection)
table.EnsureCapacity(table.Count + collection.Count);

foreach (var @event in events)
{
Expand Down Expand Up @@ -299,6 +312,17 @@ public void FinalizeTypes()
uint propertyList = 1;
uint eventList = 1;

tablesStream.GetTable<FieldPointerRow>(TableIndex.FieldPtr)
.EnsureCapacity(tablesStream.GetTable<FieldDefinitionRow>(TableIndex.Field).Count);
tablesStream.GetTable<MethodPointerRow>(TableIndex.MethodPtr)
.EnsureCapacity(tablesStream.GetTable<MethodDefinitionRow>(TableIndex.Method).Count);
tablesStream.GetTable<ParameterPointerRow>(TableIndex.ParamPtr)
.EnsureCapacity(tablesStream.GetTable<ParameterDefinitionRow>(TableIndex.Param).Count);
tablesStream.GetTable<PropertyPointerRow>(TableIndex.PropertyPtr)
.EnsureCapacity(tablesStream.GetTable<PropertyDefinitionRow>(TableIndex.Property).Count);
tablesStream.GetTable<EventPointerRow>(TableIndex.EventPtr)
.EnsureCapacity(tablesStream.GetTable<EventDefinitionRow>(TableIndex.Event).Count);

for (uint rid = 1; rid <= typeDefTable.Count; rid++)
{
var typeToken = new MetadataToken(TableIndex.TypeDef, rid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ public TRow this[uint rid]
}
}

/// <inheritdoc />
public void EnsureCapacity(int capacity)
{
_underlyingBuffer.EnsureCapacity(capacity);

#if NETSTANDARD2_1_OR_GREATER
_entries.EnsureCapacity(capacity);
#endif
}

/// <inheritdoc />
public ref TRow GetRowRef(uint rid) => ref _underlyingBuffer.GetRowRef(rid);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ TRow this[uint rid]
set;
}

/// <summary>
/// Ensures the capacity of the table buffer is at least the provided amount of elements.
/// </summary>
/// <param name="capacity">The number of elements to store.</param>
void EnsureCapacity(int capacity);

/// <summary>
/// Gets or sets a reference to a row in the metadata table.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public virtual TRow this[uint rid]
set => _entries[(int) (rid - 1)] = value;
}

/// <inheritdoc />
public void EnsureCapacity(int capacity)
{
if (_entries.Capacity < capacity)
_entries.Capacity = capacity;
}

/// <inheritdoc />
public ref TRow GetRowRef(uint rid) => ref _entries.GetElementRef((int)(rid - 1));

Expand All @@ -49,6 +56,9 @@ public virtual MetadataToken Add(in TRow row)
/// <inheritdoc />
public void FlushToTable()
{
if (_table.Capacity < _entries.Count)
_table.Capacity = _entries.Count;

foreach (var row in _entries)
_table.Add(row);
}
Expand Down
10 changes: 10 additions & 0 deletions src/AsmResolver.DotNet/Collections/MethodSemanticsCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ public MethodSemanticsCollection(IHasSemantics owner)
{
}

/// <summary>
/// Creates a new instance of the <see cref="MethodSemanticsCollection"/> class.
/// </summary>
/// <param name="owner">The owner of the collection.</param>
/// <param name="capacity">The initial number of elements the collection can store.</param>
public MethodSemanticsCollection(IHasSemantics owner, int capacity)
: base(owner, capacity)
{
}

internal bool ValidateMembership
{
get;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ public SerializedGenericParameter(ModuleReaderContext context, MetadataToken tok
/// <inheritdoc />
protected override IList<GenericParameterConstraint> GetConstraints()
{
var result = new OwnedCollection<GenericParameter, GenericParameterConstraint>(this);

var module = _context.ParentModule;
foreach (uint rid in module.GetGenericParameterConstraints(MetadataToken))
var rids = module.GetGenericParameterConstraints(MetadataToken);
var result = new OwnedCollection<GenericParameter, GenericParameterConstraint>(this, rids.Count);

foreach (uint rid in rids)
{
var constraintToken = new MetadataToken(TableIndex.GenericParamConstraint, rid);
result.Add((GenericParameterConstraint) module.LookupMember(constraintToken));
Expand Down
10 changes: 6 additions & 4 deletions src/AsmResolver.DotNet/Serialized/SerializedMethodDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ protected override IList<SecurityDeclaration> GetSecurityDeclarations() =>
/// <inheritdoc />
protected override IList<ParameterDefinition> GetParameterDefinitions()
{
var result = new OwnedCollection<MethodDefinition, ParameterDefinition>(this);
var parameterRange = _context.ParentModule.GetParameterRange(MetadataToken.Rid);
var result = new OwnedCollection<MethodDefinition, ParameterDefinition>(this, parameterRange.Count);

foreach (var token in _context.ParentModule.GetParameterRange(MetadataToken.Rid))
foreach (var token in parameterRange)
{
if (_context.ParentModule.TryLookupMember(token, out var member) && member is ParameterDefinition parameter)
result.Add(parameter);
Expand All @@ -108,9 +109,10 @@ protected override IList<ParameterDefinition> GetParameterDefinitions()
/// <inheritdoc />
protected override IList<GenericParameter> GetGenericParameters()
{
var result = new OwnedCollection<IHasGenericParameters, GenericParameter>(this);
var rids = _context.ParentModule.GetGenericParameters(MetadataToken);
var result = new OwnedCollection<IHasGenericParameters, GenericParameter>(this, rids.Count);

foreach (uint rid in _context.ParentModule.GetGenericParameters(MetadataToken))
foreach (uint rid in rids)
{
if (_context.ParentModule.TryLookupMember(new MetadataToken(TableIndex.GenericParam, rid), out var member)
&& member is GenericParameter genericParameter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private OneToManyRelation<uint, uint> InitializeTypeDefinitionTree()
return typeDefTree;
}

internal IEnumerable<uint> GetNestedTypeRids(uint enclosingTypeRid)
internal ICollection<uint> GetNestedTypeRids(uint enclosingTypeRid)
{
EnsureTypeDefinitionTreeInitialized();
return _typeDefTree.GetValues(enclosingTypeRid);
Expand Down Expand Up @@ -107,8 +107,8 @@ private void InitializeMethodSemantics()
var semanticsTable = tablesStream.GetTable<MethodSemanticsRow>(TableIndex.MethodSemantics);
var encoder = tablesStream.GetIndexEncoder(CodedIndex.HasSemantics);

var semantics = new OneToManyRelation<MetadataToken, uint>();
var semanticMethods = new Dictionary<uint, MetadataToken>();
var semantics = new OneToManyRelation<MetadataToken, uint>(semanticsTable.Count);
var semanticMethods = new Dictionary<uint, MetadataToken>(semanticsTable.Count);
for (int i = 0; i < semanticsTable.Count; i++)
{
var methodSemanticsRow = semanticsTable[i];
Expand All @@ -123,7 +123,7 @@ private void InitializeMethodSemantics()
Interlocked.CompareExchange(ref _semanticMethods, semanticMethods, null);
}

internal IEnumerable<uint> GetMethodSemantics(MetadataToken owner)
internal ICollection<uint> GetMethodSemantics(MetadataToken owner)
{
EnsureMethodSemanticsInitialized();
return _semantics.GetValues(owner);
Expand Down Expand Up @@ -155,7 +155,7 @@ private OneToOneRelation<MetadataToken, uint> GetConstants()
var constantTable = tablesStream.GetTable<ConstantRow>(TableIndex.Constant);
var encoder = tablesStream.GetIndexEncoder(CodedIndex.HasConstant);

var constants = new OneToOneRelation<MetadataToken, uint>();
var constants = new OneToOneRelation<MetadataToken, uint>(constantTable.Count);
for (int i = 0; i < constantTable.Count; i++)
{
var ownerToken = encoder.DecodeIndex(constantTable[i].Parent);
Expand Down Expand Up @@ -199,7 +199,7 @@ private OneToManyRelation<MetadataToken, uint> InitializeCustomAttributes()
var attributeTable = tablesStream.GetTable<CustomAttributeRow>(TableIndex.CustomAttribute);
var encoder = tablesStream.GetIndexEncoder(CodedIndex.HasCustomAttribute);

var customAttributes = new OneToManyRelation<MetadataToken, uint>();
var customAttributes = new OneToManyRelation<MetadataToken, uint>(attributeTable.Count);
for (int i = 0; i < attributeTable.Count; i++)
{
var ownerToken = encoder.DecodeIndex(attributeTable[i].Parent);
Expand Down Expand Up @@ -228,9 +228,10 @@ internal MetadataToken GetCustomAttributeOwner(uint attributeRid)
internal IList<CustomAttribute> GetCustomAttributeCollection(IHasCustomAttribute owner)
{
EnsureCustomAttributesInitialized();
var result = new OwnedCollection<IHasCustomAttribute, CustomAttribute>(owner);
var rids = _customAttributes.GetValues(owner.MetadataToken);
var result = new OwnedCollection<IHasCustomAttribute, CustomAttribute>(owner, rids.Count);

foreach (uint rid in _customAttributes.GetValues(owner.MetadataToken))
foreach (uint rid in rids)
{
var attribute = (CustomAttribute) LookupMember(new MetadataToken(TableIndex.CustomAttribute, rid));
result.Add(attribute);
Expand All @@ -252,7 +253,7 @@ private OneToManyRelation<MetadataToken, uint> InitializeSecurityDeclarations()
var declarationTable = tablesStream.GetTable<SecurityDeclarationRow>(TableIndex.DeclSecurity);
var encoder = tablesStream.GetIndexEncoder(CodedIndex.HasDeclSecurity);

var securityDeclarations = new OneToManyRelation<MetadataToken, uint>();
var securityDeclarations = new OneToManyRelation<MetadataToken, uint>(declarationTable.Count);
for (int i = 0; i < declarationTable.Count; i++)
{
var ownerToken = encoder.DecodeIndex(declarationTable[i].Parent);
Expand All @@ -272,9 +273,10 @@ internal MetadataToken GetSecurityDeclarationOwner(uint attributeRid)
internal IList<SecurityDeclaration> GetSecurityDeclarationCollection(IHasSecurityDeclaration owner)
{
EnsureSecurityDeclarationsInitialized();
var result = new OwnedCollection<IHasSecurityDeclaration, SecurityDeclaration>(owner);
var rids = _securityDeclarations.GetValues(owner.MetadataToken);
var result = new OwnedCollection<IHasSecurityDeclaration, SecurityDeclaration>(owner, rids.Count);

foreach (uint rid in _securityDeclarations.GetValues(owner.MetadataToken))
foreach (uint rid in rids)
{
var attribute = (SecurityDeclaration) LookupMember(new MetadataToken(TableIndex.DeclSecurity, rid));
result.Add(attribute);
Expand All @@ -296,7 +298,7 @@ private OneToManyRelation<MetadataToken, uint> InitializeGenericParameters()
var parameterTable = tablesStream.GetTable<GenericParameterRow>(TableIndex.GenericParam);
var encoder = tablesStream.GetIndexEncoder(CodedIndex.TypeOrMethodDef);

var genericParameters = new OneToManyRelation<MetadataToken, uint>();
var genericParameters = new OneToManyRelation<MetadataToken, uint>(parameterTable.Count);
for (int i = 0; i < parameterTable.Count; i++)
{
var ownerToken = encoder.DecodeIndex(parameterTable[i].Owner);
Expand Down Expand Up @@ -331,7 +333,7 @@ private OneToManyRelation<MetadataToken, uint> InitializeGenericParameterConstra
var tablesStream = DotNetDirectory.Metadata!.GetStream<TablesStream>();
var constraintTable = tablesStream.GetTable<GenericParameterConstraintRow>(TableIndex.GenericParamConstraint);

var constraints = new OneToManyRelation<MetadataToken, uint>();
var constraints = new OneToManyRelation<MetadataToken, uint>(constraintTable.Count);
for (int i = 0; i < constraintTable.Count; i++)
{
var ownerToken = new MetadataToken(TableIndex.GenericParam, constraintTable[i].Owner);
Expand Down Expand Up @@ -366,7 +368,7 @@ private OneToManyRelation<MetadataToken, uint> InitializeInterfaces()
var tablesStream = DotNetDirectory.Metadata!.GetStream<TablesStream>();
var interfaceImplTable = tablesStream.GetTable<InterfaceImplementationRow>(TableIndex.InterfaceImpl);

var interfaces = new OneToManyRelation<MetadataToken, uint>();
var interfaces = new OneToManyRelation<MetadataToken, uint>(interfaceImplTable.Count);
for (int i = 0; i < interfaceImplTable.Count; i++)
{
var ownerToken = new MetadataToken(TableIndex.TypeDef, interfaceImplTable[i].Class);
Expand Down Expand Up @@ -401,7 +403,7 @@ private OneToManyRelation<MetadataToken, uint> InitializeMethodImplementations()
var tablesStream = DotNetDirectory.Metadata!.GetStream<TablesStream>();
var methodImplTable = tablesStream.GetTable<MethodImplementationRow>(TableIndex.MethodImpl);

var methodImplementations = new OneToManyRelation<MetadataToken, uint>();
var methodImplementations = new OneToManyRelation<MetadataToken, uint>(methodImplTable.Count);
for (int i = 0; i < methodImplTable.Count; i++)
{
var ownerToken = new MetadataToken(TableIndex.TypeDef, methodImplTable[i].Class);
Expand Down Expand Up @@ -430,7 +432,7 @@ private OneToOneRelation<MetadataToken, uint> InitializeClassLayouts()
var tablesStream = DotNetDirectory.Metadata!.GetStream<TablesStream>();
var layoutTable = tablesStream.GetTable<ClassLayoutRow>(TableIndex.ClassLayout);

var layouts = new OneToOneRelation<MetadataToken, uint>();
var layouts = new OneToOneRelation<MetadataToken, uint>(layoutTable.Count);
for (int i = 0; i < layoutTable.Count; i++)
{
var ownerToken = new MetadataToken(TableIndex.TypeDef, layoutTable[i].Parent);
Expand Down Expand Up @@ -460,7 +462,7 @@ private OneToOneRelation<MetadataToken, uint> InitializeImplementationMaps()
var mapTable = tablesStream.GetTable<ImplementationMapRow>(TableIndex.ImplMap);
var encoder = tablesStream.GetIndexEncoder(CodedIndex.TypeOrMethodDef);

var maps = new OneToOneRelation<MetadataToken, uint>();
var maps = new OneToOneRelation<MetadataToken, uint>(mapTable.Count);
for (int i = 0; i < mapTable.Count; i++)
{
var ownerToken = encoder.DecodeIndex(mapTable[i].MemberForwarded);
Expand Down Expand Up @@ -495,7 +497,7 @@ private OneToOneRelation<MetadataToken, uint> InitializeFieldRvas()
var tablesStream = DotNetDirectory.Metadata!.GetStream<TablesStream>();
var rvaTable = tablesStream.GetTable<FieldRvaRow>(TableIndex.FieldRva);

var rvas = new OneToOneRelation<MetadataToken, uint>();
var rvas = new OneToOneRelation<MetadataToken, uint>(rvaTable.Count);
for (int i = 0; i < rvaTable.Count; i++)
{
var ownerToken = new MetadataToken(TableIndex.Field, rvaTable[i].Field);
Expand Down Expand Up @@ -525,7 +527,7 @@ private OneToOneRelation<MetadataToken, uint> InitializeFieldMarshals()
var marshalTable = tablesStream.GetTable<FieldMarshalRow>(TableIndex.FieldMarshal);
var encoder = tablesStream.GetIndexEncoder(CodedIndex.HasFieldMarshal);

var marshals = new OneToOneRelation<MetadataToken, uint>();
var marshals = new OneToOneRelation<MetadataToken, uint>(marshalTable.Count);
for (int i = 0; i < marshalTable.Count; i++)
{
var ownerToken = encoder.DecodeIndex(marshalTable[i].Parent);
Expand Down Expand Up @@ -571,7 +573,7 @@ private OneToOneRelation<MetadataToken, uint> InitializeFieldLayouts()
var tablesStream = DotNetDirectory.Metadata!.GetStream<TablesStream>();
var layoutTable = tablesStream.GetTable<FieldLayoutRow>(TableIndex.FieldLayout);

var fieldLayouts = new OneToOneRelation<MetadataToken, uint>();
var fieldLayouts = new OneToOneRelation<MetadataToken, uint>(layoutTable.Count);
for (int i = 0; i < layoutTable.Count; i++)
{
var ownerToken = new MetadataToken(TableIndex.Field, layoutTable[i].Field);
Expand Down
Loading

0 comments on commit 036c408

Please sign in to comment.