Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions docs/design/datacontracts/CodeVersions.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,11 @@ IEnumerable<ILCodeVersionHandle> ICodeVersions.GetILCodeVersions(TargetPointer m
GetModuleAndMethodDesc(methodDesc, out TargetPointer module, out uint methodDefToken);

ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(module);
TargetPointer ilCodeVersionTable = _target.Contracts.Loader.GetLookupTables(moduleHandle).MethodDefToILCodeVersioningState;
TargetPointer ilVersionStateAddress = _target.Contracts.Loader.GetModuleLookupMapElement(ilCodeVersionTable, methodDefToken, out var _);
TargetPointer ilVersionStateAddress = _target.Contracts.Loader.GetModuleLookupMapElement(
moduleHandle,
ModuleLookupMapKind.MethodDefToILCodeVersioningState,
methodDefToken,
out var _);

// always add the synthetic version
yield return new ILCodeVersionHandle(module, methodDefToken, TargetPointer.Null);
Expand Down
93 changes: 52 additions & 41 deletions docs/design/datacontracts/Loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ public enum AssemblyIterationFlags
IncludeCollected = 0x00000080, // Include all collectible assemblies that have been collected
}

record struct ModuleLookupTables(
TargetPointer FieldDefToDesc,
TargetPointer ManifestModuleReferences,
TargetPointer MemberRefToDesc,
TargetPointer MethodDefToDesc,
TargetPointer TypeDefToMethodTable,
TargetPointer TypeRefToMethodTable,
TargetPointer MethodDefToILCodeVersioningState,
uint TableDataOffset);
enum ModuleLookupMapKind
{
FieldDefToDesc,
ManifestModuleReferences,
MemberRefToDesc,
MethodDefToDesc,
TypeDefToMethodTable,
TypeRefToMethodTable,
MethodDefToILCodeVersioningState,
}

readonly record struct LoaderHeapBlock(TargetPointer Address, TargetNUInt Size);

Expand Down Expand Up @@ -99,10 +100,10 @@ bool GetFileHeadersInfo(ModuleHandle handle, out uint timeStamp, out uint imageS
TargetPointer GetLoaderAllocator(ModuleHandle handle);
TargetPointer GetILBase(ModuleHandle handle);
TargetPointer GetAssemblyLoadContext(ModuleHandle handle);
ModuleLookupTables GetLookupTables(ModuleHandle handle);
TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out TargetNUInt flags);
TargetPointer GetModuleLookupMapBase(ModuleHandle module, ModuleLookupMapKind kind);
TargetPointer GetModuleLookupMapElement(ModuleHandle module, ModuleLookupMapKind kind, uint token, out TargetNUInt flags);
TargetPointer LookupMemberRefAsMethod(ModuleHandle handle, uint token);
IEnumerable<(TargetPointer, uint)> EnumerateModuleLookupMap(TargetPointer table);
IEnumerable<(TargetPointer Value, uint Token)> EnumerateModuleLookupMap(ModuleHandle module, ModuleLookupMapKind kind);
bool IsCollectible(ModuleHandle handle);
bool IsDynamic(ModuleHandle handle);
bool IsModuleMapped(ModuleHandle handle);
Expand Down Expand Up @@ -711,29 +712,38 @@ TargetPointer ILoader.GetAssemblyLoadContext(ModuleHandle handle)
return objectHandle.Object;
}

ModuleLookupTables GetLookupTables(ModuleHandle handle)
TargetPointer GetModuleLookupMap(ModuleHandle module, ModuleLookupMapKind kind)
{
uint tableDataOffset = (uint)/* ModuleLookupMap::TableData offset */;
return new ModuleLookupTables(
FieldDefToDescMap: target.ReadPointer(handle.Address + /* Module::FieldDefToDescMap */),
ManifestModuleReferencesMap: target.ReadPointer(handle.Address + /* Module::ManifestModuleReferencesMap */),
MemberRefToDescMap: target.ReadPointer(handle.Address + /* Module::MemberRefToDescMap */),
MethodDefToDescMap: target.ReadPointer(handle.Address + /* Module::MethodDefToDescMap */),
TypeDefToMethodTableMap: target.ReadPointer(handle.Address + /* Module::TypeDefToMethodTableMap */),
TypeRefToMethodTableMap: target.ReadPointer(handle.Address + /* Module::TypeRefToMethodTableMap */),
// Module::MethodDefToILCodeVersioningState is only present when the target was built
// with code versioning (FEATURE_CODE_VERSIONING). When absent (e.g. on WASM) it is
// treated as a null (empty) table.
MethodDefToILCodeVersioningState: HasField(Module::MethodDefToILCodeVersioningState)
? target.ReadPointer(handle.Address + /* Module::MethodDefToILCodeVersioningState */)
: TargetPointer.Null,
TableDataOffset: tableDataOffset);
return kind switch
{
FieldDefToDesc => target.ReadPointer(module.Address + /* Module::FieldDefToDescMap offset */),
ManifestModuleReferences => target.ReadPointer(module.Address + /* Module::ManifestModuleReferencesMap offset */),
MemberRefToDesc => target.ReadPointer(module.Address + /* Module::MemberRefToDescMap offset */),
MethodDefToDesc => target.ReadPointer(module.Address + /* Module::MethodDefToDescMap offset */),
TypeDefToMethodTable => target.ReadPointer(module.Address + /* Module::TypeDefToMethodTableMap offset */),
TypeRefToMethodTable => target.ReadPointer(module.Address + /* Module::TypeRefToMethodTableMap offset */),
MethodDefToILCodeVersioningState => target.ReadPointer(module.Address + /* Module::MethodDefToILCodeVersioningStateMap offset */),
};
}

TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out TargetNUInt flags);
TargetPointer GetModuleLookupMapBase(ModuleHandle module, ModuleLookupMapKind kind)
{
TargetPointer table = GetModuleLookupMap(module, kind);
return table == TargetPointer.Null
? TargetPointer.Null
: target.ReadPointer(table + /* ModuleLookupMap::TableData offset */);
}

uint CreateModuleLookupMapToken(ModuleLookupMapKind kind, uint rid)
{
// Combine rid with the metadata table prefix implied by kind.
}

TargetPointer GetModuleLookupMapElement(ModuleHandle module, ModuleLookupMapKind kind, uint token, out TargetNUInt flags)
{
uint rid = /* get row id from token*/ (token);
flags = new TargetNUInt(0);
TargetPointer table = GetModuleLookupMap(module, kind);
if (table == TargetPointer.Null)
return TargetPointer.Null;
uint index = rid;
Expand All @@ -742,34 +752,35 @@ TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out Tar
TargetNUInt supportedFlagsMask = target.ReadNUInt(table + /* ModuleLookupMap::SupportedFlagsMask */);
do
{
if (index < target.Read<uint>(table + /*ModuleLookupMap::Count*/))
uint count = target.Read<uint>(table + /*ModuleLookupMap::Count*/);
if (index < count)
{
TargetPointer entryAddress = target.ReadPointer(lookupMap + /*ModuleLookupMap::TableData*/) + (ulong)(index * target.PointerSize);
TargetPointer entryAddress = target.ReadPointer(table + /*ModuleLookupMap::TableData*/) + (ulong)(index * target.PointerSize);
TargetPointer rawValue = target.ReadPointer(entryAddress);
flags = rawValue & supportedFlagsMask;
return rawValue & ~(supportedFlagsMask.Value);
}
else
{
table = target.ReadPointer(lookupMap + /*ModuleLookupMap::Next*/);
index -= target.Read<uint>(lookupMap + /*ModuleLookupMap::Count*/);
index -= count;
table = target.ReadPointer(table + /*ModuleLookupMap::Next*/);
}
} while (table != TargetPointer.Null);
return TargetPointer.Null;
}

// Returns the MethodDesc pointer for the given mdMemberRef token, or TargetPointer.Null
// if the entry is a FieldDesc (flagged with IS_FIELD_MEMBER_REF) or not present.
TargetPointer LookupMemberRefAsMethod(ModuleHandle handle, uint memberRefToken)
TargetPointer LookupMemberRefAsMethod(ModuleHandle module, uint token)
{
ModuleLookupTables tables = GetLookupTables(handle);
TargetPointer result = GetModuleLookupMapElement(tables.MemberRefToDesc, memberRefToken, out TargetNUInt flags);
TargetPointer result = GetModuleLookupMapElement(module, MemberRefToDesc, token, out TargetNUInt flags);
return (flags.Value & IS_FIELD_MEMBER_REF) == 0 ? result : TargetPointer.Null;
}

IEnumerable<(TargetPointer, uint)> EnumerateModuleLookupMap(TargetPointer table)
IEnumerable<(TargetPointer Value, uint Token)> EnumerateModuleLookupMap(ModuleHandle module, ModuleLookupMapKind kind)
{
Data.ModuleLookupMap lookupMap = new Data.ModuleLookupMap(table);
TargetPointer table = GetModuleLookupMap(module, kind);
if (table == TargetPointer.Null)
yield break;

// have to read lookupMap an extra time upfront because only the first map
// has valid supportedFlagsMask
TargetNUInt supportedFlagsMask = target.ReadNUInt(table + /* ModuleLookupMap::SupportedFlagsMask */);
Expand All @@ -783,7 +794,7 @@ IEnumerable<(TargetPointer, uint)> EnumerateModuleLookupMap(TargetPointer table)
TargetPointer rawValue = target.ReadPointer(entryAddress);
ulong maskedValue = rawValue & ~(supportedFlagsMask.Value);
if (maskedValue != 0)
yield return (new TargetPointer(maskedValue), index);
yield return (new TargetPointer(maskedValue), CreateModuleLookupMapToken(kind, index));
index++;
}
else
Expand Down
7 changes: 5 additions & 2 deletions docs/design/datacontracts/ManagedTypeSource.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,11 @@ bool TryResolveType(

// Resolve the TypeDef token via the module's TypeDef -> MethodTable map.
int token = MetadataTokens.GetToken(typeDefHandle);
TargetPointer typeDefToMT = loader.GetLookupTables(moduleHandle).TypeDefToMethodTable;
TargetPointer mt = loader.GetModuleLookupMapElement(typeDefToMT, (uint)token, out _);
TargetPointer mt = loader.GetModuleLookupMapElement(
moduleHandle,
ModuleLookupMapKind.TypeDefToMethodTable,
(uint)token,
out _);
if (mt == TargetPointer.Null)
return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ public static bool TryResolveAssemblyRefToModule(

uint token = (uint)MetadataTokens.GetToken(assemblyRef);

ModuleLookupTables tables = loader.GetLookupTables(referencingModule);
TargetPointer modulePtr = loader.GetModuleLookupMapElement(tables.ManifestModuleReferences, token, out _);
TargetPointer modulePtr = loader.GetModuleLookupMapElement(
referencingModule,
ModuleLookupMapKind.ManifestModuleReferences,
token,
out _);
if (modulePtr == TargetPointer.Null)
return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,16 @@ public enum AssemblyIterationFlags
IncludeCollected = 0x00000080, // Include all collectible assemblies that have been collected
}

public record struct ModuleLookupTables(
TargetPointer FieldDefToDesc,
TargetPointer ManifestModuleReferences,
TargetPointer MemberRefToDesc,
TargetPointer MethodDefToDesc,
TargetPointer TypeDefToMethodTable,
TargetPointer TypeRefToMethodTable,
TargetPointer MethodDefToILCodeVersioningState,
uint TableDataOffset);
public enum ModuleLookupMapKind
{
FieldDefToDesc,
ManifestModuleReferences,
MemberRefToDesc,
MethodDefToDesc,
TypeDefToMethodTable,
TypeRefToMethodTable,
MethodDefToILCodeVersioningState,
}
Comment thread
max-charlamb marked this conversation as resolved.

public readonly record struct LoaderHeapBlock(TargetPointer Address, TargetNUInt Size);

Expand Down Expand Up @@ -114,10 +115,10 @@ public interface ILoader : IContract
TargetPointer GetLoaderAllocator(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetILBase(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetAssemblyLoadContext(ModuleHandle handle) => throw new NotImplementedException();
ModuleLookupTables GetLookupTables(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out TargetNUInt flags) => throw new NotImplementedException();
TargetPointer GetModuleLookupMapBase(ModuleHandle module, ModuleLookupMapKind kind) => throw new NotImplementedException();
TargetPointer GetModuleLookupMapElement(ModuleHandle module, ModuleLookupMapKind kind, uint token, out TargetNUInt flags) => throw new NotImplementedException();
TargetPointer LookupMemberRefAsMethod(ModuleHandle handle, uint token) => throw new NotImplementedException();
IEnumerable<(TargetPointer, uint)> EnumerateModuleLookupMap(TargetPointer table) => throw new NotImplementedException();
IEnumerable<(TargetPointer Value, uint Token)> EnumerateModuleLookupMap(ModuleHandle module, ModuleLookupMapKind kind) => throw new NotImplementedException();
Comment thread
max-charlamb marked this conversation as resolved.
bool IsCollectible(ModuleHandle handle) => throw new NotImplementedException();
bool IsDynamic(ModuleHandle handle) => throw new NotImplementedException();
bool IsModuleMapped(ModuleHandle handle) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,11 @@ private TargetPointer GetILVersionStateAddress(TargetPointer module, uint method
return TargetPointer.Null;

ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(module);
TargetPointer ilCodeVersionTable = _target.Contracts.Loader.GetLookupTables(moduleHandle).MethodDefToILCodeVersioningState;
TargetPointer ilVersionStateAddress = _target.Contracts.Loader.GetModuleLookupMapElement(ilCodeVersionTable, methodDefToken, out var _);
TargetPointer ilVersionStateAddress = _target.Contracts.Loader.GetModuleLookupMapElement(
moduleHandle,
ModuleLookupMapKind.MethodDefToILCodeVersioningState,
methodDefToken,
out var _);
return ilVersionStateAddress;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,12 +560,11 @@ private bool IsObjectType(TargetPointer moduleAddr, uint classToken)
{
ILoader loader = _target.Contracts.Loader;
ModuleHandle module = loader.GetModuleHandleFromModulePtr(moduleAddr);
ModuleLookupTables tables = loader.GetLookupTables(module);

TargetPointer resolvedMethodTable = (EcmaMetadataUtils.TokenType)(classToken & EcmaMetadataUtils.TokenTypeMask) switch
{
EcmaMetadataUtils.TokenType.mdtTypeDef => loader.GetModuleLookupMapElement(tables.TypeDefToMethodTable, classToken, out _),
EcmaMetadataUtils.TokenType.mdtTypeRef => loader.GetModuleLookupMapElement(tables.TypeRefToMethodTable, classToken, out _),
EcmaMetadataUtils.TokenType.mdtTypeDef => loader.GetModuleLookupMapElement(module, ModuleLookupMapKind.TypeDefToMethodTable, classToken, out _),
EcmaMetadataUtils.TokenType.mdtTypeRef => loader.GetModuleLookupMapElement(module, ModuleLookupMapKind.TypeRefToMethodTable, classToken, out _),
_ => TargetPointer.Null,
};

Expand Down
Loading
Loading