From 8023cc3340cf824e7e8a798e3576b4852811e3cc Mon Sep 17 00:00:00 2001 From: jfrijters Date: Wed, 2 May 2012 15:24:00 +0000 Subject: [PATCH] Changed table sort implementation to reuse the ISortKey interface and switched to a stable sort. --- reflect/Metadata/Tables.cs | 184 +++++++++++-------------------------- 1 file changed, 52 insertions(+), 132 deletions(-) diff --git a/reflect/Metadata/Tables.cs b/reflect/Metadata/Tables.cs index c9721154..107b5ce9 100644 --- a/reflect/Metadata/Tables.cs +++ b/reflect/Metadata/Tables.cs @@ -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 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 comparer) - { - Array.Sort(records, 0, rowCount, comparer); - } -#endif } - abstract class SortedTable : Table + abstract class SortedTable : Table, IComparer where T : SortedTable.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.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 @@ -889,7 +875,7 @@ namespace IKVM.Reflection.Metadata } } - sealed class InterfaceImplTable : SortedTable, IComparer + sealed class InterfaceImplTable : SortedTable { internal const int Index = 0x09; @@ -953,22 +939,10 @@ namespace IKVM.Reflection.Metadata } records[i].Interface = token; } - Sort(this); - } - - int IComparer.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, IComparer + sealed class ConstantTable : SortedTable { internal const int Index = 0x0B; @@ -1102,12 +1076,7 @@ namespace IKVM.Reflection.Metadata throw new InvalidOperationException(); } } - Array.Sort(records, 0, rowCount, this); - } - - int IComparer.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, IComparer + sealed class CustomAttributeTable : SortedTable { internal const int Index = 0x0C; @@ -1283,16 +1252,11 @@ namespace IKVM.Reflection.Metadata throw new InvalidOperationException(); } } - Sort(this); - } - - int IComparer.Compare(Record x, Record y) - { - return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1); + Sort(); } } - sealed class FieldMarshalTable : SortedTable, IComparer + sealed class FieldMarshalTable : SortedTable { internal const int Index = 0x0D; @@ -1351,16 +1315,11 @@ namespace IKVM.Reflection.Metadata throw new InvalidOperationException(); } } - Array.Sort(records, 0, rowCount, this); - } - - int IComparer.Compare(Record x, Record y) - { - return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1); + Sort(); } } - sealed class DeclSecurityTable : SortedTable, IComparer + sealed class DeclSecurityTable : SortedTable { internal const int Index = 0x0E; @@ -1428,16 +1387,11 @@ namespace IKVM.Reflection.Metadata } records[i].Parent = token; } - Sort(this); - } - - int IComparer.Compare(Record x, Record y) - { - return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1); + Sort(); } } - sealed class ClassLayoutTable : SortedTable, IComparer + sealed class ClassLayoutTable : SortedTable { 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.Compare(Record x, Record y) - { - return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1); - } } - sealed class FieldLayoutTable : SortedTable, IComparer + sealed class FieldLayoutTable : SortedTable { 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.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, IComparer + sealed class MethodSemanticsTable : SortedTable { internal const int Index = 0x18; @@ -1847,12 +1791,7 @@ namespace IKVM.Reflection.Metadata } records[i].Association = token; } - Sort(this); - } - - int IComparer.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, IComparer + sealed class MethodImplTable : SortedTable { 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.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, IComparer + sealed class ImplMapTable : SortedTable { 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.Compare(Record x, Record y) - { - return x.MemberForwarded == y.MemberForwarded ? 0 : (x.MemberForwarded > y.MemberForwarded ? 1 : -1); + Sort(); } } - sealed class FieldRVATable : SortedTable, IComparer + sealed class FieldRVATable : SortedTable { 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.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) cast is a workaround for a .NET 2.0 C# compiler bug + Array.Sort(records, 0, rowCount, (IComparer)this); } int IComparer.Compare(Record x, Record y) @@ -2683,7 +2608,7 @@ namespace IKVM.Reflection.Metadata } } - sealed class GenericParamConstraintTable : SortedTable, IComparer + sealed class GenericParamConstraintTable : SortedTable { 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.Compare(Record x, Record y) - { - return x.Owner == y.Owner ? 0 : (x.Owner > y.Owner ? 1 : -1); + Sort(); } } }