зеркало из https://github.com/mono/ikvm-fork.git
Changed table sort implementation to reuse the ISortKey interface and switched to a stable sort.
This commit is contained in:
Родитель
784b32110e
Коммит
8023cc3340
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче