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
74 changes: 45 additions & 29 deletions docs/design/datacontracts/RuntimeTypeSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,18 @@ partial interface IRuntimeTypeSystem : IContract
// True if the MethodTable represents a type that contains managed references
public virtual bool ContainsGCPointers(TypeHandle typeHandle);
public virtual bool IsDynamicStatics(TypeHandle typeHandle);
public virtual ushort GetNumMethods(TypeHandle typeHandle);
public virtual ushort GetNumInterfaces(TypeHandle typeHandle);

// Returns an ECMA-335 TypeDef table token for this type, or for its generic type definition if it is a generic instantiation
public virtual uint GetTypeDefToken(TypeHandle typeHandle);
public virtual ushort GetNumMethods(TypeHandle typeHandle);
// Returns the ECMA 335 TypeDef table Flags value (a bitmask of TypeAttributes) for this type,
// or for its generic type definition if it is a generic instantiation
public virtual uint GetTypeDefTypeAttributes(TypeHandle typeHandle);
public ushort GetNumInstanceFields(TypeHandle typeHandle);
public ushort GetNumStaticFields(TypeHandle typeHandle);
public ushort GetNumThreadStaticFields(TypeHandle typeHandle);
public TargetPointer GetFieldDescList(TypeHandle typeHandle);
public virtual ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle typeHandle);
public virtual bool IsGenericTypeDefinition(TypeHandle typeHandle);

Expand Down Expand Up @@ -348,6 +352,10 @@ The contract additionally depends on these data descriptors
| `EEClass` | `NumMethods` | Count of methods attached to the EEClass |
| `EEClass` | `NumNonVirtualSlots` | Count of non-virtual slots for the EEClass |
| `EEClass` | `CorTypeAttr` | Various flags |
| `EEClass` | `NumInstanceFields` | Count of instance fields of the EEClass |
| `EEClass` | `NumStaticFields` | Count of static fields of the EEClass |
| `EEClass` | `NumThreadStaticFields` | Count of threadstatic fields of the EEClass |
| `EEClass` | `FieldDescList` | A list of fields in the type |
| `ArrayClass` | `Rank` | Rank of the associated array MethodTable |
| `TypeDesc` | `TypeAndFlags` | The lower 8 bits are the CorElementType of the `TypeDesc`, the upper 24 bits are reserved for flags |
| `ParamTypeDesc` | `TypeArg` | Associated type argument |
Expand All @@ -374,11 +382,35 @@ The contract additionally depends on these data descriptors
return TypeHandle { Address = typeHandlePointer }
}

public TargetPointer GetModule(TypeHandle TypeHandle)
{
if (typeHandle.IsMethodTable())
{
return _methodTables[TypeHandle.Address].Module;
}
else if (typeHandle.IsTypeDesc())
{
if (HasTypeParam(typeHandle))
{
return GetModule(GetTypeParam(typeHandle));
}
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
{
return genericParamModule;
}
}
return TargetPointer.Null;
}

internal static EEClassOrCanonMTBits GetEEClassOrCanonMTBits(TargetPointer eeClassOrCanonMTPtr)
{
return (EEClassOrCanonMTBits)(eeClassOrCanonMTPtr & (ulong)EEClassOrCanonMTBits.Mask);
}

public TargetPointer GetCanonicalMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable;

public TargetPointer GetParentMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[TypeHandle.Address].ParentMethodTable;

public uint GetBaseSize(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[TypeHandle.Address].Flags.BaseSize;

public uint GetComponentSize(TypeHandle TypeHandle) =>!typeHandle.IsMethodTable() ? (uint)0 : GetComponentSize(_methodTables[TypeHandle.Address]);
Expand All @@ -397,36 +429,16 @@ The contract additionally depends on these data descriptors
... // read Data.EEClass data from eeClassPtr
}


public TargetPointer GetCanonicalMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable;

public TargetPointer GetModule(TypeHandle TypeHandle)
{
if (typeHandle.IsMethodTable())
{
return _methodTables[TypeHandle.Address].Module;
}
else if (typeHandle.IsTypeDesc())
{
if (HasTypeParam(typeHandle))
{
return GetModule(GetTypeParam(typeHandle));
}
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
{
return genericParamModule;
}
}
return TargetPointer.Null;
}

public TargetPointer GetParentMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[TypeHandle.Address].ParentMethodTable;

public bool IsFreeObjectMethodTable(TypeHandle TypeHandle) => FreeObjectMethodTablePointer == TypeHandle.Address;

public bool IsString(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsString;

public bool ContainsGCPointers(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.ContainsGCPointers;

public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics;

public ushort GetNumInterfaces(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces;

public uint GetTypeDefToken(TypeHandle TypeHandle)
{
if (!typeHandle.IsMethodTable())
Expand All @@ -438,11 +450,15 @@ The contract additionally depends on these data descriptors

public ushort GetNumMethods(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).NumMethods;

public ushort GetNumInterfaces(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces;

public uint GetTypeDefTypeAttributes(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).CorTypeAttr;

public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics;
public ushort GetNumInstanceFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields;

public ushort GetNumStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields;

public ushort GetNumThreadStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields;

public TargetPointer GetFieldDescList(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).FieldDescList;

public ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle TypeHandle)
{
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,12 @@ CDAC_TYPE_BEGIN(EEClass)
CDAC_TYPE_INDETERMINATE(EEClass)
CDAC_TYPE_FIELD(EEClass, /*pointer*/, MethodTable, cdac_data<EEClass>::MethodTable)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumMethods, cdac_data<EEClass>::NumMethods)
CDAC_TYPE_FIELD(EEClass, /*pointer*/, FieldDescList, cdac_data<EEClass>::FieldDescList)
CDAC_TYPE_FIELD(EEClass, /*uint32*/, CorTypeAttr, cdac_data<EEClass>::CorTypeAttr)
CDAC_TYPE_FIELD(EEClass, /*uint8*/, InternalCorElementType, cdac_data<EEClass>::InternalCorElementType)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumInstanceFields, cdac_data<EEClass>::NumInstanceFields)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumStaticFields, cdac_data<EEClass>::NumStaticFields)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumThreadStaticFields, cdac_data<EEClass>::NumThreadStaticFields)
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumNonVirtualSlots, cdac_data<EEClass>::NumNonVirtualSlots)
CDAC_TYPE_END(EEClass)

Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/vm/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -1799,8 +1799,12 @@ template<> struct cdac_data<EEClass>
{
static constexpr size_t InternalCorElementType = offsetof(EEClass, m_NormType);
static constexpr size_t MethodTable = offsetof(EEClass, m_pMethodTable);
static constexpr size_t FieldDescList = offsetof(EEClass, m_pFieldDescList);
static constexpr size_t NumMethods = offsetof(EEClass, m_NumMethods);
static constexpr size_t CorTypeAttr = offsetof(EEClass, m_dwAttrClass);
static constexpr size_t NumInstanceFields = offsetof(EEClass, m_NumInstanceFields);
static constexpr size_t NumStaticFields = offsetof(EEClass, m_NumStaticFields);
static constexpr size_t NumThreadStaticFields = offsetof(EEClass, m_NumThreadStaticFields);
static constexpr size_t NumNonVirtualSlots = offsetof(EEClass, m_NumNonVirtualSlots);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,19 @@ public interface IRuntimeTypeSystem : IContract
// True if the MethodTable represents a type that contains managed references
bool ContainsGCPointers(TypeHandle typeHandle) => throw new NotImplementedException();
bool IsDynamicStatics(TypeHandle typeHandle) => throw new NotImplementedException();
ushort GetNumMethods(TypeHandle typeHandle) => throw new NotImplementedException();
ushort GetNumInterfaces(TypeHandle typeHandle) => throw new NotImplementedException();

// Returns an ECMA-335 TypeDef table token for this type, or for its generic type definition if it is a generic instantiation
uint GetTypeDefToken(TypeHandle typeHandle) => throw new NotImplementedException();
ushort GetNumMethods(TypeHandle typeHandle) => throw new NotImplementedException();
// Returns the ECMA 335 TypeDef table Flags value (a bitmask of TypeAttributes) for this type,
// or for its generic type definition if it is a generic instantiation
uint GetTypeDefTypeAttributes(TypeHandle typeHandle) => throw new NotImplementedException();
ushort GetNumInstanceFields(TypeHandle typeHandle) => throw new NotImplementedException();
ushort GetNumStaticFields(TypeHandle typeHandle) => throw new NotImplementedException();
ushort GetNumThreadStaticFields(TypeHandle typeHandle) => throw new NotImplementedException();
TargetPointer GetFieldDescList(TypeHandle typeHandle) => throw new NotImplementedException();


ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle typeHandle) => throw new NotImplementedException();
bool IsGenericTypeDefinition(TypeHandle typeHandle) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,35 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer)
_ = _methodTables.TryAdd(methodTablePointer, trustedMethodTableF);
return new TypeHandle(methodTablePointer);
}
public TargetPointer GetModule(TypeHandle typeHandle)
{
if (typeHandle.IsMethodTable())
{
return _methodTables[typeHandle.Address].Module;
}
else if (typeHandle.IsTypeDesc())
{
if (HasTypeParam(typeHandle))
{
return GetModule(GetTypeParam(typeHandle));
}
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
{
return genericParamModule;
}
else
{
System.Diagnostics.Debug.Assert(IsFunctionPointer(typeHandle, out _, out _));
return TargetPointer.Null;
}
}
else
{
return TargetPointer.Null;
}
}
public TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable;
public TargetPointer GetParentMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[typeHandle.Address].ParentMethodTable;

public uint GetBaseSize(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.BaseSize;

Expand Down Expand Up @@ -343,42 +372,13 @@ private Data.EEClass GetClassData(TypeHandle typeHandle)
return _target.ProcessedData.GetOrAdd<Data.EEClass>(clsPtr);
}

public TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable;

public TargetPointer GetModule(TypeHandle typeHandle)
{
if (typeHandle.IsMethodTable())
{
return _methodTables[typeHandle.Address].Module;
}
else if (typeHandle.IsTypeDesc())
{
if (HasTypeParam(typeHandle))
{
return GetModule(GetTypeParam(typeHandle));
}
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
{
return genericParamModule;
}
else
{
System.Diagnostics.Debug.Assert(IsFunctionPointer(typeHandle, out _, out _));
return TargetPointer.Null;
}
}
else
{
return TargetPointer.Null;
}
}

public TargetPointer GetParentMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[typeHandle.Address].ParentMethodTable;

public bool IsFreeObjectMethodTable(TypeHandle typeHandle) => FreeObjectMethodTablePointer == typeHandle.Address;

public bool IsString(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsString;
public bool ContainsGCPointers(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.ContainsGCPointers;
public bool IsDynamicStatics(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsDynamicStatics;
public ushort GetNumInterfaces(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : _methodTables[typeHandle.Address].NumInterfaces;

public uint GetTypeDefToken(TypeHandle typeHandle)
{
Expand All @@ -387,14 +387,13 @@ public uint GetTypeDefToken(TypeHandle typeHandle)
MethodTable methodTable = _methodTables[typeHandle.Address];
return (uint)(methodTable.Flags.GetTypeDefRid() | ((int)TableIndex.TypeDef << 24));
}

public ushort GetNumMethods(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumMethods;

public ushort GetNumInterfaces(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : _methodTables[typeHandle.Address].NumInterfaces;

public uint GetTypeDefTypeAttributes(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : GetClassData(typeHandle).CorTypeAttr;
public ushort GetNumInstanceFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields;
public ushort GetNumStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields;
public ushort GetNumThreadStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields;
public TargetPointer GetFieldDescList(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).FieldDescList;

public bool IsDynamicStatics(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsDynamicStatics;

public ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle typeHandle)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public EEClass(Target target, TargetPointer address)
NumMethods = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumMethods)].Offset);
CorTypeAttr = target.Read<uint>(address + (ulong)type.Fields[nameof(CorTypeAttr)].Offset);
InternalCorElementType = target.Read<byte>(address + (ulong)type.Fields[nameof(InternalCorElementType)].Offset);
NumInstanceFields = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumInstanceFields)].Offset);
NumStaticFields = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumStaticFields)].Offset);
NumThreadStaticFields = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumThreadStaticFields)].Offset);
FieldDescList = target.Read<ulong>(address + (ulong)type.Fields[nameof(FieldDescList)].Offset);
NumNonVirtualSlots = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumNonVirtualSlots)].Offset);
}

Expand All @@ -29,7 +33,10 @@ public EEClass(Target target, TargetPointer address)
// Enums are the element type of their underlying type
// ValueTypes which can exactly be represented as an element type are represented as such
public byte InternalCorElementType { get; init; }

public ushort NumInstanceFields { get; init; }
public ushort NumStaticFields { get; init; }
public ushort NumThreadStaticFields { get; init; }
public TargetPointer FieldDescList { get; init; }
public ushort NumNonVirtualSlots { get; init; }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ internal struct DacpUsefulGlobalsData
}
#pragma warning restore CS0649 // Field is never assigned to, and will always have its default value

internal struct DacpMethodTableFieldData
{
public ushort wNumInstanceFields;
public ushort wNumStaticFields;
public ushort wNumThreadStaticFields;
public ClrDataAddress FirstField;
public ushort wContextStaticOffset;
public ushort wContextStaticsSize;
};

internal struct DacpReJitData
{
// FIXME[cdac]: the C++ definition enum doesn't have an explicit underlying type or constant values for the flags
Expand Down Expand Up @@ -276,7 +286,7 @@ internal unsafe partial interface ISOSDacInterface
[PreserveSig]
int GetMethodTableSlot(ClrDataAddress mt, uint slot, ClrDataAddress* value);
[PreserveSig]
int GetMethodTableFieldData(ClrDataAddress mt, /*struct DacpMethodTableFieldData*/ void* data);
int GetMethodTableFieldData(ClrDataAddress mt, DacpMethodTableFieldData* data);
[PreserveSig]
int GetMethodTableTransparencyData(ClrDataAddress mt, /*struct DacpMethodTableTransparencyData*/ void* data);

Expand Down
Loading
Loading