зеркало из 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();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if STABLE_SORT
|
|
||||||
private struct OrdinalWrapper
|
|
||||||
{
|
|
||||||
internal int ordinal;
|
|
||||||
internal T value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Sort(IComparer<T> comparer)
|
abstract class SortedTable<T> : Table<T>, IComparer<int>
|
||||||
{
|
|
||||||
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>
|
|
||||||
where T : SortedTable<T>.ISortKey
|
where T : SortedTable<T>.ISortKey
|
||||||
{
|
{
|
||||||
internal interface ISortKey
|
internal interface ISortKey
|
||||||
|
@ -569,6 +533,28 @@ namespace IKVM.Reflection.Metadata
|
||||||
{
|
{
|
||||||
return new Enumerable(this, token);
|
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>
|
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;
|
internal const int Index = 0x09;
|
||||||
|
|
||||||
|
@ -953,22 +939,10 @@ namespace IKVM.Reflection.Metadata
|
||||||
}
|
}
|
||||||
records[i].Interface = token;
|
records[i].Interface = token;
|
||||||
}
|
}
|
||||||
Sort(this);
|
// 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).
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
Sort();
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
internal const int Index = 0x0B;
|
||||||
|
|
||||||
|
@ -1102,12 +1076,7 @@ namespace IKVM.Reflection.Metadata
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Array.Sort(records, 0, rowCount, this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object GetRawConstantValue(Module module, int parent)
|
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;
|
internal const int Index = 0x0C;
|
||||||
|
|
||||||
|
@ -1283,16 +1252,11 @@ namespace IKVM.Reflection.Metadata
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Sort(this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class FieldMarshalTable : SortedTable<FieldMarshalTable.Record>, IComparer<FieldMarshalTable.Record>
|
sealed class FieldMarshalTable : SortedTable<FieldMarshalTable.Record>
|
||||||
{
|
{
|
||||||
internal const int Index = 0x0D;
|
internal const int Index = 0x0D;
|
||||||
|
|
||||||
|
@ -1351,16 +1315,11 @@ namespace IKVM.Reflection.Metadata
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Array.Sort(records, 0, rowCount, this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class DeclSecurityTable : SortedTable<DeclSecurityTable.Record>, IComparer<DeclSecurityTable.Record>
|
sealed class DeclSecurityTable : SortedTable<DeclSecurityTable.Record>
|
||||||
{
|
{
|
||||||
internal const int Index = 0x0E;
|
internal const int Index = 0x0E;
|
||||||
|
|
||||||
|
@ -1428,16 +1387,11 @@ namespace IKVM.Reflection.Metadata
|
||||||
}
|
}
|
||||||
records[i].Parent = token;
|
records[i].Parent = token;
|
||||||
}
|
}
|
||||||
Sort(this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Parent == y.Parent ? 0 : (x.Parent > y.Parent ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class ClassLayoutTable : SortedTable<ClassLayoutTable.Record>, IComparer<ClassLayoutTable.Record>
|
sealed class ClassLayoutTable : SortedTable<ClassLayoutTable.Record>
|
||||||
{
|
{
|
||||||
internal const int Index = 0x0f;
|
internal const int Index = 0x0f;
|
||||||
|
|
||||||
|
@ -1465,7 +1419,7 @@ namespace IKVM.Reflection.Metadata
|
||||||
|
|
||||||
internal override void Write(MetadataWriter mw)
|
internal override void Write(MetadataWriter mw)
|
||||||
{
|
{
|
||||||
Array.Sort(records, 0, rowCount, this);
|
Sort();
|
||||||
for (int i = 0; i < rowCount; i++)
|
for (int i = 0; i < rowCount; i++)
|
||||||
{
|
{
|
||||||
mw.Write(records[i].PackingSize);
|
mw.Write(records[i].PackingSize);
|
||||||
|
@ -1481,14 +1435,9 @@ namespace IKVM.Reflection.Metadata
|
||||||
.WriteTypeDef()
|
.WriteTypeDef()
|
||||||
.Value;
|
.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;
|
internal const int Index = 0x10;
|
||||||
|
|
||||||
|
@ -1535,12 +1484,7 @@ namespace IKVM.Reflection.Metadata
|
||||||
{
|
{
|
||||||
records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
|
records[i].Field = moduleBuilder.ResolvePseudoToken(records[i].Field);
|
||||||
}
|
}
|
||||||
Array.Sort(records, 0, rowCount, this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
internal const int Index = 0x18;
|
||||||
|
|
||||||
|
@ -1847,12 +1791,7 @@ namespace IKVM.Reflection.Metadata
|
||||||
}
|
}
|
||||||
records[i].Association = token;
|
records[i].Association = token;
|
||||||
}
|
}
|
||||||
Sort(this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Association == y.Association ? 0 : (x.Association > y.Association ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal MethodInfo GetMethod(Module module, int token, bool nonPublic, short semantics)
|
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;
|
internal const int Index = 0x19;
|
||||||
|
|
||||||
|
@ -1955,12 +1894,7 @@ namespace IKVM.Reflection.Metadata
|
||||||
moduleBuilder.FixupPseudoToken(ref records[i].MethodBody);
|
moduleBuilder.FixupPseudoToken(ref records[i].MethodBody);
|
||||||
moduleBuilder.FixupPseudoToken(ref records[i].MethodDeclaration);
|
moduleBuilder.FixupPseudoToken(ref records[i].MethodDeclaration);
|
||||||
}
|
}
|
||||||
Sort(this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Class == y.Class ? 0 : (x.Class > y.Class ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
internal const int Index = 0x1C;
|
||||||
|
|
||||||
|
@ -2085,16 +2019,11 @@ namespace IKVM.Reflection.Metadata
|
||||||
{
|
{
|
||||||
moduleBuilder.FixupPseudoToken(ref records[i].MemberForwarded);
|
moduleBuilder.FixupPseudoToken(ref records[i].MemberForwarded);
|
||||||
}
|
}
|
||||||
Array.Sort(records, 0, rowCount, this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.MemberForwarded == y.MemberForwarded ? 0 : (x.MemberForwarded > y.MemberForwarded ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class FieldRVATable : SortedTable<FieldRVATable.Record>, IComparer<FieldRVATable.Record>
|
sealed class FieldRVATable : SortedTable<FieldRVATable.Record>
|
||||||
{
|
{
|
||||||
internal const int Index = 0x1D;
|
internal const int Index = 0x1D;
|
||||||
|
|
||||||
|
@ -2149,12 +2078,7 @@ namespace IKVM.Reflection.Metadata
|
||||||
}
|
}
|
||||||
moduleBuilder.FixupPseudoToken(ref records[i].Field);
|
moduleBuilder.FixupPseudoToken(ref records[i].Field);
|
||||||
}
|
}
|
||||||
Array.Sort(records, 0, rowCount, this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Field == y.Field ? 0 : (x.Field > y.Field ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2588,7 +2512,8 @@ namespace IKVM.Reflection.Metadata
|
||||||
}
|
}
|
||||||
records[i].unsortedIndex = i;
|
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)
|
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;
|
internal const int Index = 0x2C;
|
||||||
|
|
||||||
|
@ -2731,12 +2656,7 @@ namespace IKVM.Reflection.Metadata
|
||||||
{
|
{
|
||||||
records[i].Owner = fixups[records[i].Owner - 1] + 1;
|
records[i].Owner = fixups[records[i].Owner - 1] + 1;
|
||||||
}
|
}
|
||||||
Sort(this);
|
Sort();
|
||||||
}
|
|
||||||
|
|
||||||
int IComparer<Record>.Compare(Record x, Record y)
|
|
||||||
{
|
|
||||||
return x.Owner == y.Owner ? 0 : (x.Owner > y.Owner ? 1 : -1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче