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
8 changes: 7 additions & 1 deletion docs/design/datacontracts/RuntimeTypeSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ partial interface IRuntimeTypeSystem : IContract

// True if the MethodTable is the sentinel value associated with unallocated space in the managed heap
public virtual bool IsFreeObjectMethodTable(TypeHandle typeHandle);
// True if the MethodTable is the System.Object MethodTable (g_pObjectClass)
public virtual bool IsObject(TypeHandle typeHandle);
public virtual bool IsString(TypeHandle typeHandle);
// True if the type is a GC-collectable object reference.
public virtual bool IsObjRef(TypeHandle typeHandle);
Expand Down Expand Up @@ -439,7 +441,8 @@ The contract depends on the following globals
| Global name | Meaning |
| --- | --- |
| `ContinuationMethodTable` | A pointer to the address of the base `Continuation` `MethodTable`, or null if no continuations have been created
| `FreeObjectMethodTablePointer` | A pointer to the address of a `MethodTable` used by the GC to indicate reclaimed memory
| `FreeObjectMethodTable` | A pointer to the address of a `MethodTable` used by the GC to indicate reclaimed memory
| `ObjectMethodTable` | A pointer to the address of the `System.Object` `MethodTable` (`g_pObjectClass`)
| `StaticsPointerMask` | For masking out a bit of DynamicStaticsInfo pointer fields
| `ArrayBaseSize` | The base size of an array object; used to compute multidimensional array rank from `MethodTable::BaseSize`

Expand Down Expand Up @@ -512,6 +515,7 @@ Contracts used:
private readonly Dictionary<TargetPointer, MethodTable_1> _methodTables;

internal TargetPointer FreeObjectMethodTablePointer {get; }
internal TargetPointer ObjectMethodTablePointer {get; }
internal TargetPointer ContinuationMethodTablePointer {get; }

public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer)
Expand Down Expand Up @@ -572,6 +576,8 @@ Contracts used:

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

public bool IsObject(TypeHandle TypeHandle) => ObjectMethodTablePointer != TargetPointer.Null && ObjectMethodTablePointer == TypeHandle.Address;

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

public bool IsObjRef(TypeHandle typeHandle) => // Returns true if GetSignatureCorElementType returns Class, Array, or SzArray.
Expand Down
41 changes: 7 additions & 34 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2513,28 +2513,13 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle
} // DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo


HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, COR_TYPEID id, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo)
{
DD_ENTER_MAY_THROW;

HRESULT hr = S_OK;
EX_TRY
{

TypeHandleToExpandedTypeInfoImpl(boxed, TypeHandle::FromPtr(TO_TADDR(id.token1)), pTypeInfo);
}
EX_CATCH_HRESULT(hr);
return hr;
}

HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, CORDB_ADDRESS addr, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo)
{
DD_ENTER_MAY_THROW;

HRESULT hr = S_OK;
EX_TRY
{

PTR_Object obj(TO_TADDR(addr));
TypeHandleToExpandedTypeInfoImpl(boxed, obj->GetGCSafeTypeHandle(), pTypeInfo);
}
Expand All @@ -2543,16 +2528,14 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetObjectExpandedTypeInfo(AreValu
}

// DacDbi API: use a type handle to get the information needed to create the corresponding RS CordbType instance
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_TypeHandle vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo)
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, CORDB_ADDRESS vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo)
{
DD_ENTER_MAY_THROW;

HRESULT hr = S_OK;
EX_TRY
{


TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr());
TypeHandle typeHandle = TypeHandle::FromPtr((TADDR)vmTypeHandle);
TypeHandleToExpandedTypeInfoImpl(boxed, typeHandle, pTypeInfo);
}
EX_CATCH_HRESULT(hr);
Expand All @@ -2564,6 +2547,7 @@ void DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfoImpl(AreValueTypesBoxed
TypeHandle typeHandle,
DebuggerIPCE_ExpandedTypeData * pTypeInfo)
{
*pTypeInfo = {};
pTypeInfo->elementType = GetElementType(typeHandle);

switch (pTypeInfo->elementType)
Expand Down Expand Up @@ -2776,20 +2760,16 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetMethodDescParams(VMPTR_MethodD
EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
{
// Fill in the struct using the TypeHandle of the current type parameter if we can.
VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
vmTypeHandle.SetDacTargetPtr(thCurrent.AsTAddr());
IfFailThrow(TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
vmTypeHandle,
(CORDB_ADDRESS)thCurrent.AsTAddr(),
&((*pGenericTypeParams)[i])));
}
EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
{
// On failure for a particular type, default it back to System.__Canon.
VMPTR_TypeHandle vmTHCanon = VMPTR_TypeHandle::NullPtr();
TypeHandle thCanon = TypeHandle(g_pCanonMethodTableClass);
vmTHCanon.SetDacTargetPtr(thCanon.AsTAddr());
IfFailThrow(TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
vmTHCanon,
(CORDB_ADDRESS)thCanon.AsTAddr(),
&((*pGenericTypeParams)[i])));
}
EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
Expand Down Expand Up @@ -3214,11 +3194,8 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetTypeHandleParams(VMPTR_TypeHan
// collect type information for each type parameter
for (unsigned int i = 0; i < pParams->Count(); ++i)
{
VMPTR_TypeHandle thInst = VMPTR_TypeHandle::NullPtr();
thInst.SetDacTargetPtr(typeHandle.GetInstantiation()[i].AsTAddr());

IfFailThrow(TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
thInst,
(CORDB_ADDRESS)typeHandle.GetInstantiation()[i].AsTAddr(),
&((*pParams)[i])));
}

Expand Down Expand Up @@ -6092,15 +6069,11 @@ void DacDbiInterfaceImpl::InitObjectData(PTR_Object objPtr,
DebuggerIPCE_ObjectData * pObjectData)
{
_ASSERTE(pObjectData != NULL);
// @todo - this is still dangerous because the object may still be invalid.
VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
vmTypeHandle.SetDacTargetPtr(objPtr->GetGCSafeTypeHandle().AsTAddr());

// Save basic object info.
pObjectData->objSize = objPtr->GetSize();
pObjectData->objOffsetToVars = dac_cast<TADDR>((objPtr)->GetData()) - dac_cast<TADDR>(objPtr);

IfFailThrow(TypeHandleToExpandedTypeInfo(AllBoxed, vmTypeHandle, &(pObjectData->objTypeData)));
IfFailThrow(TypeHandleToExpandedTypeInfo(AllBoxed, (CORDB_ADDRESS)objPtr->GetGCSafeTypeHandle().AsTAddr(), &(pObjectData->objTypeData)));

// If this is a string object, set the type to ELEMENT_TYPE_STRING.
if (objPtr->GetGCSafeMethodTable() == g_pStringClass)
Expand Down
5 changes: 1 addition & 4 deletions src/coreclr/debug/daccess/dacdbiimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,10 @@ class DacDbiInterfaceImpl :
HRESULT STDMETHODCALLTYPE GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, CORDB_ADDRESS addr, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo);


HRESULT STDMETHODCALLTYPE GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, COR_TYPEID id, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo);


// @dbgtodo Microsoft inspection: change DebuggerIPCE_ExpandedTypeData to DacDbiStructures type hierarchy
// once ICorDebugType and ICorDebugClass are DACized
// use a type handle to get the information needed to create the corresponding RS CordbType instance
HRESULT STDMETHODCALLTYPE TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_TypeHandle vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo);
HRESULT STDMETHODCALLTYPE TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, CORDB_ADDRESS vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo);

// Get type handle for a TypeDef token, if one exists. For generics this returns the open type.
HRESULT STDMETHODCALLTYPE GetTypeHandle(VMPTR_Module vmModule, mdTypeDef metadataToken, OUT VMPTR_TypeHandle * pRetVal);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/di/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2370,7 +2370,7 @@ HRESULT CordbProcess::GetTypeForTypeID(COR_TYPEID id, ICorDebugType **ppType)
EX_TRY
{
DebuggerIPCE_ExpandedTypeData data;
IfFailThrow(GetDAC()->GetObjectExpandedTypeInfoFromID(AllBoxed, id, &data));
IfFailThrow(GetDAC()->TypeHandleToExpandedTypeInfo(AllBoxed, id.token1, &data));

CordbType *type = 0;
hr = CordbType::TypeDataToType(GetAppDomain(), &data, &type);
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/debug/di/rstype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1163,8 +1163,11 @@ HRESULT CordbType::TypeDataToType(CordbAppDomain *pAppDomain, DebuggerIPCE_Basic

{
RSLockHolder lockHolder(pProcess->GetProcessLock());
CORDB_ADDRESS vmTypeHandleRaw = 0;
static_assert(sizeof(data->vmTypeHandle) <= sizeof(vmTypeHandleRaw), "VMPTR_TypeHandle is larger than CORDB_ADDRESS");
memcpy(&vmTypeHandleRaw, &data->vmTypeHandle, sizeof(data->vmTypeHandle));
IfFailThrow(pProcess->GetDAC()->TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, // could be generics which are never boxed
data->vmTypeHandle,
vmTypeHandleRaw,
&typeInfo));
}

Expand Down
5 changes: 1 addition & 4 deletions src/coreclr/debug/inc/dacdbiinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1549,14 +1549,11 @@ IDacDbiInterface : public IUnknown
// vmTypeHandle - type handle for the type
// output: pTypeInfo - holds information needed to build the corresponding CordbType
//
virtual HRESULT STDMETHODCALLTYPE TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, VMPTR_TypeHandle vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0;
virtual HRESULT STDMETHODCALLTYPE TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, CORDB_ADDRESS vmTypeHandle, DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0;

virtual HRESULT STDMETHODCALLTYPE GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, CORDB_ADDRESS addr, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0;


virtual HRESULT STDMETHODCALLTYPE GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed, COR_TYPEID id, OUT DebuggerIPCE_ExpandedTypeData * pTypeInfo) = 0;


// Get type handle for a TypeDef token, if one exists. For generics this returns the open type.
// Note there is no guarantee the returned handle will be fully restored (in pre-jit scenarios),
// only that it exists. Later functions that use this type handle should fail if they require
Expand Down
7 changes: 6 additions & 1 deletion src/coreclr/debug/inc/dacdbistructures.h
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,12 @@ class MSLAYOUT EnCHangingFieldInfo
// NoValueTypeBoxing:
// TypeHandleToExpandedTypeInfo is also used to report type parameters,
// and in this case none of the types are considered boxed (
enum AreValueTypesBoxed { NoValueTypeBoxing, OnlyPrimitivesUnboxed, AllBoxed };
enum AreValueTypesBoxed
{
NoValueTypeBoxing = 0,
OnlyPrimitivesUnboxed = 1,
AllBoxed = 2
};
Comment thread
rcj1 marked this conversation as resolved.
Comment thread
rcj1 marked this conversation as resolved.

// TypeRefData is used for resolving a type reference (see code:CordbModule::ResolveTypeRef and
// code:DacDbiInterfaceImpl::ResolveTypeReference) to store relevant information about the type
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/inc/dacdbi.idl
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,8 @@ interface IDacDbiInterface : IUnknown
[in] VMPTR_TypeHandle vmThApprox,
[out] DacDbiArrayList_FieldData * pFieldList,
[out] SIZE_T * pObjectSize);
HRESULT TypeHandleToExpandedTypeInfo([in] AreValueTypesBoxed boxed, [in] VMPTR_TypeHandle vmTypeHandle, [out] struct DebuggerIPCE_ExpandedTypeData * pTypeInfo);
HRESULT TypeHandleToExpandedTypeInfo([in] AreValueTypesBoxed boxed, [in] CORDB_ADDRESS vmTypeHandle, [out] struct DebuggerIPCE_ExpandedTypeData * pTypeInfo);
HRESULT GetObjectExpandedTypeInfo([in] AreValueTypesBoxed boxed, [in] CORDB_ADDRESS addr, [out] struct DebuggerIPCE_ExpandedTypeData * pTypeInfo);
HRESULT GetObjectExpandedTypeInfoFromID([in] AreValueTypesBoxed boxed, [in] COR_TYPEID id, [out] struct DebuggerIPCE_ExpandedTypeData * pTypeInfo);
HRESULT GetTypeHandle([in] VMPTR_Module vmModule, [in] mdTypeDef metadataToken, [out] VMPTR_TypeHandle * pRetVal);
HRESULT GetApproxTypeHandle([in] TypeInfoList * pTypeData, [out] VMPTR_TypeHandle * pRetVal);
HRESULT GetExactTypeHandle([in] struct DebuggerIPCE_ExpandedTypeData * pTypeData, [in] ArgInfoList * pArgInfo, [out] VMPTR_TypeHandle * pVmTypeHandle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ public interface IRuntimeTypeSystem : IContract

// True if the MethodTable is the sentinel value associated with unallocated space in the managed heap
bool IsFreeObjectMethodTable(TypeHandle typeHandle) => throw new NotImplementedException();
// True if the MethodTable is the System.Object MethodTable (g_pObjectClass)
bool IsObject(TypeHandle typeHandle) => throw new NotImplementedException();
bool IsString(TypeHandle typeHandle) => throw new NotImplementedException();
Comment thread
rcj1 marked this conversation as resolved.
Comment thread
rcj1 marked this conversation as resolved.
bool IsObjRef(TypeHandle typeHandle) => throw new NotImplementedException();
// True if the MethodTable represents a type that contains managed references
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal partial struct RuntimeTypeSystem_1 : IRuntimeTypeSystem
private const int TYPE_MASK_OFFSET = 27; // offset of type in field desc flags2
private readonly Target _target;
private readonly TargetPointer _freeObjectMethodTablePointer;
private readonly TargetPointer _objectMethodTablePointer;
private readonly TargetPointer _continuationMethodTablePointer;
private readonly ulong _methodDescAlignment;
private readonly TypeValidation _typeValidation;
Expand Down Expand Up @@ -433,6 +434,8 @@ internal RuntimeTypeSystem_1(Target target)
_target = target;
_freeObjectMethodTablePointer = target.ReadPointer(
target.ReadGlobalPointer(Constants.Globals.FreeObjectMethodTable));
_objectMethodTablePointer = target.ReadPointer(
target.ReadGlobalPointer(Constants.Globals.ObjectMethodTable));
_continuationMethodTablePointer = target.ReadPointer(
target.ReadGlobalPointer(Constants.Globals.ContinuationMethodTable));
_methodDescAlignment = target.ReadGlobal<ulong>(Constants.Globals.MethodDescAlignment);
Expand All @@ -442,6 +445,7 @@ internal RuntimeTypeSystem_1(Target target)
}

internal TargetPointer FreeObjectMethodTablePointer => _freeObjectMethodTablePointer;
internal TargetPointer ObjectMethodTablePointer => _objectMethodTablePointer;
internal TargetPointer ContinuationMethodTablePointer => _continuationMethodTablePointer;

internal ulong MethodDescAlignment => _methodDescAlignment;
Expand Down Expand Up @@ -560,6 +564,8 @@ private Data.EEClass GetClassData(TypeHandle typeHandle)

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

public bool IsObject(TypeHandle typeHandle) => ObjectMethodTablePointer != TargetPointer.Null && ObjectMethodTablePointer == typeHandle.Address;

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