Bug fix. Don't do the HasCustomAttribute and HasFieldMarshal in the tables, but only when writing the final data. Previously we weren't able to lookup anything in these tables after the module was saved.

This commit is contained in:
jfrijters 2012-07-13 09:12:28 +00:00
Родитель 322d9d5906
Коммит 082658b212
2 изменённых файлов: 191 добавлений и 124 удалений

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

@ -426,11 +426,12 @@ namespace IKVM.Reflection.Metadata
}
abstract class SortedTable<T> : Table<T>, IComparer<int>
where T : SortedTable<T>.ISortKey
where T : SortedTable<T>.IRecord
{
internal interface ISortKey
internal interface IRecord
{
int Key { get; }
int SortKey { get; }
int FilterKey { get; }
}
internal struct Enumerable
@ -457,13 +458,13 @@ namespace IKVM.Reflection.Metadata
return new Enumerator(null, 0, 1, -1);
}
int start = index;
while (start > 0 && (records[start - 1].Key & 0xFFFFFF) == (token & 0xFFFFFF))
while (start > 0 && (records[start - 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF))
{
start--;
}
int end = index;
int max = table.RowCount - 1;
while (end < max && (records[end + 1].Key & 0xFFFFFF) == (token & 0xFFFFFF))
while (end < max && (records[end + 1].FilterKey & 0xFFFFFF) == (token & 0xFFFFFF))
{
end++;
}
@ -477,7 +478,7 @@ namespace IKVM.Reflection.Metadata
while (min <= max)
{
int mid = min + ((max - min) / 2);
int maskedValue = records[mid].Key & 0xFFFFFF;
int maskedValue = records[mid].FilterKey & 0xFFFFFF;
if (maskedToken == maskedValue)
{
return mid;
@ -520,7 +521,7 @@ namespace IKVM.Reflection.Metadata
while (index < max)
{
index++;
if (records[index].Key == token)
if (records[index].FilterKey == token)
{
return true;
}
@ -552,7 +553,7 @@ namespace IKVM.Reflection.Metadata
int IComparer<int>.Compare(int x, int y)
{
int rc = records[x].Key.CompareTo(records[y].Key);
int rc = records[x].SortKey.CompareTo(records[y].SortKey);
return rc == 0 ? x.CompareTo(y) : rc;
}
}
@ -879,12 +880,17 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x09;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Class;
internal int Interface;
int ISortKey.Key
int IRecord.SortKey
{
get { return Class; }
}
int IRecord.FilterKey
{
get { return Class; }
}
@ -1013,13 +1019,18 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x0B;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal short Type;
internal int Parent;
internal int Value;
int ISortKey.Key
int IRecord.SortKey
{
get { return Parent; }
}
int IRecord.FilterKey
{
get { return Parent; }
}
@ -1138,13 +1149,18 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x0C;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Parent;
internal int Type;
internal int Value;
int ISortKey.Key
int IRecord.SortKey
{
get { return EncodeHasCustomAttribute(Parent); }
}
int IRecord.FilterKey
{
get { return Parent; }
}
@ -1185,87 +1201,79 @@ namespace IKVM.Reflection.Metadata
for (int i = 0; i < rowCount; i++)
{
moduleBuilder.FixupPseudoToken(ref records[i].Type);
int token = records[i].Parent;
moduleBuilder.FixupPseudoToken(ref token);
// do the HasCustomAttribute encoding, so that we can sort the table
switch (token >> 24)
moduleBuilder.FixupPseudoToken(ref records[i].Parent);
if (records[i].Parent >> 24 == GenericParamTable.Index)
{
case MethodDefTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 0;
break;
case FieldTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 1;
break;
case TypeRefTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 2;
break;
case TypeDefTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 3;
break;
case ParamTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 4;
break;
case InterfaceImplTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 5;
break;
case MemberRefTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 6;
break;
case ModuleTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 7;
break;
// Permission (8) table doesn't exist in the spec
case PropertyTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 9;
break;
case EventTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 10;
break;
case StandAloneSigTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 11;
break;
case ModuleRefTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 12;
break;
case TypeSpecTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 13;
break;
case AssemblyTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 14;
break;
case AssemblyRefTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 15;
break;
case FileTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 16;
break;
case ExportedTypeTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 17;
break;
case ManifestResourceTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 5 | 18;
break;
case GenericParamTable.Index:
records[i].Parent = (genericParamFixup[(token & 0xFFFFFF) - 1] + 1) << 5 | 19;
break;
default:
throw new InvalidOperationException();
records[i].Parent = (GenericParamTable.Index << 24) + genericParamFixup[(records[i].Parent & 0xFFFFFF) - 1] + 1;
}
}
Sort();
}
internal static int EncodeHasCustomAttribute(int token)
{
switch (token >> 24)
{
case MethodDefTable.Index:
return (token & 0xFFFFFF) << 5 | 0;
case FieldTable.Index:
return (token & 0xFFFFFF) << 5 | 1;
case TypeRefTable.Index:
return (token & 0xFFFFFF) << 5 | 2;
case TypeDefTable.Index:
return (token & 0xFFFFFF) << 5 | 3;
case ParamTable.Index:
return (token & 0xFFFFFF) << 5 | 4;
case InterfaceImplTable.Index:
return (token & 0xFFFFFF) << 5 | 5;
case MemberRefTable.Index:
return (token & 0xFFFFFF) << 5 | 6;
case ModuleTable.Index:
return (token & 0xFFFFFF) << 5 | 7;
// Permission (8) table doesn't exist in the spec
case PropertyTable.Index:
return (token & 0xFFFFFF) << 5 | 9;
case EventTable.Index:
return (token & 0xFFFFFF) << 5 | 10;
case StandAloneSigTable.Index:
return (token & 0xFFFFFF) << 5 | 11;
case ModuleRefTable.Index:
return (token & 0xFFFFFF) << 5 | 12;
case TypeSpecTable.Index:
return (token & 0xFFFFFF) << 5 | 13;
case AssemblyTable.Index:
return (token & 0xFFFFFF) << 5 | 14;
case AssemblyRefTable.Index:
return (token & 0xFFFFFF) << 5 | 15;
case FileTable.Index:
return (token & 0xFFFFFF) << 5 | 16;
case ExportedTypeTable.Index:
return (token & 0xFFFFFF) << 5 | 17;
case ManifestResourceTable.Index:
return (token & 0xFFFFFF) << 5 | 18;
case GenericParamTable.Index:
return (token & 0xFFFFFF) << 5 | 19;
default:
throw new InvalidOperationException();
}
}
}
sealed class FieldMarshalTable : SortedTable<FieldMarshalTable.Record>
{
internal const int Index = 0x0D;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Parent;
internal int NativeType;
int ISortKey.Key
int IRecord.SortKey
{
get { return EncodeHasFieldMarshal(Parent); }
}
int IRecord.FilterKey
{
get { return Parent; }
}
@ -1301,35 +1309,41 @@ namespace IKVM.Reflection.Metadata
{
for (int i = 0; i < rowCount; i++)
{
int token = moduleBuilder.ResolvePseudoToken(records[i].Parent);
// do the HasFieldMarshal encoding, so that we can sort the table
switch (token >> 24)
{
case FieldTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 1 | 0;
break;
case ParamTable.Index:
records[i].Parent = (token & 0xFFFFFF) << 1 | 1;
break;
default:
throw new InvalidOperationException();
}
records[i].Parent = moduleBuilder.ResolvePseudoToken(records[i].Parent);
}
Sort();
}
internal static int EncodeHasFieldMarshal(int token)
{
switch (token >> 24)
{
case FieldTable.Index:
return (token & 0xFFFFFF) << 1 | 0;
case ParamTable.Index:
return (token & 0xFFFFFF) << 1 | 1;
default:
throw new InvalidOperationException();
}
}
}
sealed class DeclSecurityTable : SortedTable<DeclSecurityTable.Record>
{
internal const int Index = 0x0E;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal short Action;
internal int Parent;
internal int PermissionSet;
int ISortKey.Key
int IRecord.SortKey
{
get { return Parent; }
}
int IRecord.FilterKey
{
get { return Parent; }
}
@ -1395,13 +1409,18 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x0f;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal short PackingSize;
internal int ClassSize;
internal int Parent;
int ISortKey.Key
int IRecord.SortKey
{
get { return Parent; }
}
int IRecord.FilterKey
{
get { return Parent; }
}
@ -1441,12 +1460,17 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x10;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Offset;
internal int Field;
int ISortKey.Key
int IRecord.SortKey
{
get { return Field; }
}
int IRecord.FilterKey
{
get { return Field; }
}
@ -1530,12 +1554,17 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x12;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Parent;
internal int EventList;
int ISortKey.Key
int IRecord.SortKey
{
get { return Parent; }
}
int IRecord.FilterKey
{
get { return Parent; }
}
@ -1626,12 +1655,17 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x15;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Parent;
internal int PropertyList;
int ISortKey.Key
int IRecord.SortKey
{
get { return Parent; }
}
int IRecord.FilterKey
{
get { return Parent; }
}
@ -1730,13 +1764,18 @@ namespace IKVM.Reflection.Metadata
internal const short RemoveOn = 0x0010;
internal const short Fire = 0x0020;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal short Semantics;
internal int Method;
internal int Association;
int ISortKey.Key
int IRecord.SortKey
{
get { return Association; }
}
int IRecord.FilterKey
{
get { return Association; }
}
@ -1846,13 +1885,18 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x19;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Class;
internal int MethodBody;
internal int MethodDeclaration;
int ISortKey.Key
int IRecord.SortKey
{
get { return Class; }
}
int IRecord.FilterKey
{
get { return Class; }
}
@ -1968,14 +2012,19 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x1C;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal short MappingFlags;
internal int MemberForwarded;
internal int ImportName;
internal int ImportScope;
int ISortKey.Key
int IRecord.SortKey
{
get { return MemberForwarded; }
}
int IRecord.FilterKey
{
get { return MemberForwarded; }
}
@ -2027,12 +2076,17 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x1D;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int RVA; // we set the high bit to signify that the RVA is in the CIL stream (instead of .sdata)
internal int Field;
int ISortKey.Key
int IRecord.SortKey
{
get { return Field; }
}
int IRecord.FilterKey
{
get { return Field; }
}
@ -2391,12 +2445,17 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x29;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int NestedClass;
internal int EnclosingClass;
int ISortKey.Key
int IRecord.SortKey
{
get { return NestedClass; }
}
int IRecord.FilterKey
{
get { return NestedClass; }
}
@ -2446,7 +2505,7 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x2A;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal short Number;
internal short Flags;
@ -2455,7 +2514,12 @@ namespace IKVM.Reflection.Metadata
// not part of the table, we use it to be able to fixup the GenericParamConstraint table
internal int unsortedIndex;
int ISortKey.Key
int IRecord.SortKey
{
get { return Owner; }
}
int IRecord.FilterKey
{
get { return Owner; }
}
@ -2612,12 +2676,17 @@ namespace IKVM.Reflection.Metadata
{
internal const int Index = 0x2C;
internal struct Record : ISortKey
internal struct Record : IRecord
{
internal int Owner;
internal int Constraint;
int ISortKey.Key
int IRecord.SortKey
{
get { return Owner; }
}
int IRecord.FilterKey
{
get { return Owner; }
}

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

@ -223,10 +223,9 @@ namespace IKVM.Reflection.Writer
}
}
internal void WriteHasCustomAttribute(int encodedToken)
internal void WriteHasCustomAttribute(int token)
{
// NOTE because we've already had to do the encoding (to be able to sort the table)
// here we simple write the value
int encodedToken = CustomAttributeTable.EncodeHasCustomAttribute(token);
if (bigHasCustomAttribute)
{
Write(encodedToken);
@ -547,13 +546,12 @@ namespace IKVM.Reflection.Writer
}
}
internal void WriteHasFieldMarshal(int encodedToken)
internal void WriteHasFieldMarshal(int token)
{
// NOTE because we've already had to do the encoding (to be able to sort the table)
// here we simple write the value
int encodedToken = FieldMarshalTable.EncodeHasFieldMarshal(token);
if (bigHasFieldMarshal)
{
Write(encodedToken & 0xFFFFFF);
Write(encodedToken);
}
else
{