Changed table sort implementation to reuse the ISortKey interface and switched to a stable sort.

This commit is contained in:
jfrijters 2012-05-02 15:24:00 +00:00
Родитель 784b32110e
Коммит 8023cc3340
1 изменённых файлов: 52 добавлений и 132 удалений

Просмотреть файл

@ -423,45 +423,9 @@ namespace IKVM.Reflection.Metadata
{
throw new InvalidOperationException();
}
#if STABLE_SORT
private struct OrdinalWrapper
{
internal int ordinal;
internal T value;
}
protected void Sort(IComparer<T> comparer)
{
OrdinalWrapper[] items = new OrdinalWrapper[rowCount];
for (int i = 0; i < items.Length; i++)
{
items[i].ordinal = i;
items[i].value = records[i];
}
Array.Sort(items, delegate(OrdinalWrapper x, OrdinalWrapper y)
{
int res = comparer.Compare(x.value, y.value);
if (res == 0)
{
res = x.ordinal.CompareTo(y.ordinal);
}
return res;
});
for (int i = 0; i < items.Length; i++)
{
records[i] = items[i].value;
}
}
#else
protected void Sort(IComparer<T> comparer)
{
Array.Sort(records, 0, rowCount, comparer);
}
#endif
}
abstract class SortedTable<T> : Table<T>
abstract class SortedTable<T> : Table<T>, IComparer<int>
where T : SortedTable<T>.ISortKey
{
internal interface ISortKey
@ -569,6 +533,28 @@ namespace IKVM.Reflection.Metadata
{
return new Enumerable(this, token);
}
protected void Sort()
{
int[] map = new int[rowCount];
for (int i = 0; i < map.Length; i++)
{
map[i] = i;
}
Array.Sort(map, this);
T[] newRecords = new T[rowCount];
for (int i = 0; i < map.Length; i++)
{
newRecords[i] = records[map[i]];
}
records = newRecords;
}
int IComparer<int>.Compare(int x, int y)
{
int rc = records[x].Key.CompareTo(records[y].Key);
return rc == 0 ? x.CompareTo(y) : rc;
}
}
sealed class ModuleTable : Table<ModuleTable.Record>
@ -889,7 +875,7 @@ namespace IKVM.Reflection.Metadata
}
}
sealed class InterfaceImplTable : SortedTable<InterfaceImplTable.Record>, IComparer<InterfaceImplTable.Record>
sealed class InterfaceImplTable : SortedTable<InterfaceImplTable.Record>
{
internal const int Index = 0x09;
@ -953,22 +939,10 @@ namespace IKVM.Reflection.Metadata
}
records[i].Interface = token;
}
Sort(this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
if (x.Class == y.Class)
{
#if STABLE_SORT
return 0;
#else
// LAMESPEC the CLI spec says that InterfaceImpl should be sorted by { Class, Interface }, but it appears to be
// only necessary to sort by Class.
return x.Interface == y.Interface ? 0 : (x.Interface > y.Interface ? 1 : -1);
#endif
}
return x.Class > y.Class ? 1 : -1;
// LAMESPEC the CLI spec says that InterfaceImpl should be sorted by { Class, Interface },
// but it appears to only be necessary to sort by Class (and csc emits InterfaceImpl records in
// source file order, so to be able to support round tripping, we need to retain ordering as well).
Sort();
}
}
@ -1035,7 +1009,7 @@ namespace IKVM.Reflection.Metadata
}
}
sealed class ConstantTable : SortedTable<ConstantTable.Record>, IComparer<ConstantTable.Record>
sealed class ConstantTable : SortedTable<ConstantTable.Record>
{
internal const int Index = 0x0B;
@ -1102,12 +1076,7 @@ namespace IKVM.Reflection.Metadata
throw new InvalidOperationException();
}
}
Array.Sort(records, 0, rowCount, this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
Sort();
}
internal object GetRawConstantValue(Module module, int parent)
@ -1165,7 +1134,7 @@ namespace IKVM.Reflection.Metadata
}
}
sealed class CustomAttributeTable : SortedTable<CustomAttributeTable.Record>, IComparer<CustomAttributeTable.Record>
sealed class CustomAttributeTable : SortedTable<CustomAttributeTable.Record>
{
internal const int Index = 0x0C;
@ -1283,16 +1252,11 @@ namespace IKVM.Reflection.Metadata
throw new InvalidOperationException();
}
}
Sort(this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
Sort();
}
}
sealed class FieldMarshalTable : SortedTable<FieldMarshalTable.Record>, IComparer<FieldMarshalTable.Record>
sealed class FieldMarshalTable : SortedTable<FieldMarshalTable.Record>
{
internal const int Index = 0x0D;
@ -1351,16 +1315,11 @@ namespace IKVM.Reflection.Metadata
throw new InvalidOperationException();
}
}
Array.Sort(records, 0, rowCount, this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
Sort();
}
}
sealed class DeclSecurityTable : SortedTable<DeclSecurityTable.Record>, IComparer<DeclSecurityTable.Record>
sealed class DeclSecurityTable : SortedTable<DeclSecurityTable.Record>
{
internal const int Index = 0x0E;
@ -1428,16 +1387,11 @@ namespace IKVM.Reflection.Metadata
}
records[i].Parent = token;
}
Sort(this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
Sort();
}
}
sealed class ClassLayoutTable : SortedTable<ClassLayoutTable.Record>, IComparer<ClassLayoutTable.Record>
sealed class ClassLayoutTable : SortedTable<ClassLayoutTable.Record>
{
internal const int Index = 0x0f;
@ -1465,7 +1419,7 @@ namespace IKVM.Reflection.Metadata
internal override void Write(MetadataWriter mw)
{
Array.Sort(records, 0, rowCount, this);
Sort();
for (int i = 0; i < rowCount; i++)
{
mw.Write(records[i].PackingSize);
@ -1481,14 +1435,9 @@ namespace IKVM.Reflection.Metadata
.WriteTypeDef()
.Value;
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
}
}
sealed class FieldLayoutTable : SortedTable<FieldLayoutTable.Record>, IComparer<FieldLayoutTable.Record>
sealed class FieldLayoutTable : SortedTable<FieldLayoutTable.Record>
{
internal const int Index = 0x10;
@ -1535,12 +1484,7 @@ namespace IKVM.Reflection.Metadata
{
records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
}
Array.Sort(records, 0, rowCount, this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
Sort();
}
}
@ -1774,7 +1718,7 @@ namespace IKVM.Reflection.Metadata
}
}
sealed class MethodSemanticsTable : SortedTable<MethodSemanticsTable.Record>, IComparer<MethodSemanticsTable.Record>
sealed class MethodSemanticsTable : SortedTable<MethodSemanticsTable.Record>
{
internal const int Index = 0x18;
@ -1847,12 +1791,7 @@ namespace IKVM.Reflection.Metadata
}
records[i].Association = token;
}
Sort(this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Association == y.Association ? 0 : (x.Association > y.Association ? 1 : -1);
Sort();
}
internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics)
@ -1903,7 +1842,7 @@ namespace IKVM.Reflection.Metadata
}
}
sealed class MethodImplTable : SortedTable<MethodImplTable.Record>, IComparer<MethodImplTable.Record>
sealed class MethodImplTable : SortedTable<MethodImplTable.Record>
{
internal const int Index = 0x19;
@ -1955,12 +1894,7 @@ namespace IKVM.Reflection.Metadata
moduleBuilder.FixupPseudoToken(ref records[i].MethodBody);
moduleBuilder.FixupPseudoToken(ref records[i].MethodDeclaration);
}
Sort(this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Class == y.Class ? 0 : (x.Class > y.Class ? 1 : -1);
Sort();
}
}
@ -2030,7 +1964,7 @@ namespace IKVM.Reflection.Metadata
}
}
sealed class ImplMapTable : SortedTable<ImplMapTable.Record>, IComparer<ImplMapTable.Record>
sealed class ImplMapTable : SortedTable<ImplMapTable.Record>
{
internal const int Index = 0x1C;
@ -2085,16 +2019,11 @@ namespace IKVM.Reflection.Metadata
{
moduleBuilder.FixupPseudoToken(ref records[i].MemberForwarded);
}
Array.Sort(records, 0, rowCount, this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.MemberForwarded == y.MemberForwarded ? 0 : (x.MemberForwarded > y.MemberForwarded ? 1 : -1);
Sort();
}
}
sealed class FieldRVATable : SortedTable<FieldRVATable.Record>, IComparer<FieldRVATable.Record>
sealed class FieldRVATable : SortedTable<FieldRVATable.Record>
{
internal const int Index = 0x1D;
@ -2149,12 +2078,7 @@ namespace IKVM.Reflection.Metadata
}
moduleBuilder.FixupPseudoToken(ref records[i].Field);
}
Array.Sort(records, 0, rowCount, this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
Sort();
}
}
@ -2588,7 +2512,8 @@ namespace IKVM.Reflection.Metadata
}
records[i].unsortedIndex = i;
}
Array.Sort(records, 0, rowCount, this);
// FXBUG the unnecessary (IComparer<Record>) cast is a workaround for a .NET 2.0 C# compiler bug
Array.Sort(records, 0, rowCount, (IComparer<Record>)this);
}
int IComparer<Record>.Compare(Record x, Record y)
@ -2683,7 +2608,7 @@ namespace IKVM.Reflection.Metadata
}
}
sealed class GenericParamConstraintTable : SortedTable<GenericParamConstraintTable.Record>, IComparer<GenericParamConstraintTable.Record>
sealed class GenericParamConstraintTable : SortedTable<GenericParamConstraintTable.Record>
{
internal const int Index = 0x2C;
@ -2731,12 +2656,7 @@ namespace IKVM.Reflection.Metadata
{
records[i].Owner = fixups[records[i].Owner - 1] + 1;
}
Sort(this);
}
int IComparer<Record>.Compare(Record x, Record y)
{
return x.Owner == y.Owner ? 0 : (x.Owner > y.Owner ? 1 : -1);
Sort();
}
}
}