From 7323824cdcf63323ab5352997cf9cc7a3bbb2e93 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Wed, 24 Jun 2026 09:58:12 -0400 Subject: [PATCH 01/23] [cdac] Rename TypeHandle to ITypeHandle Rename the TypeHandle struct to ITypeHandle across the entire cDAC codebase in preparation for converting it to an interface that supports synthetic type handles for unloaded constructed types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../CdacAttributes.cs | 4 +- .../Contracts/IManagedTypeSource.cs | 4 +- .../Contracts/IRuntimeMutableTypeSystem.cs | 2 +- .../Contracts/IRuntimeTypeSystem.cs | 144 +++++------ .../Contracts/ISignature.cs | 2 +- .../Contracts/CodeVersions_1.cs | 4 +- .../Contracts/ComWrappers_1.cs | 2 +- .../Contracts/ConditionalWeakTable_1.cs | 2 +- .../Contracts/Exception_1.cs | 2 +- .../ExecutionManager/ExecutionManagerCore.cs | 2 +- .../Contracts/ManagedTypeSource_1.cs | 24 +- .../Contracts/Object_1.cs | 4 +- .../Contracts/RuntimeMutableTypeSystem_1.cs | 2 +- .../Contracts/RuntimeTypeSystem_1.cs | 240 +++++++++--------- .../IRuntimeSignatureTypeProvider.cs | 4 +- .../Signature/SignatureTypeProvider.cs | 46 ++-- .../Contracts/Signature/Signature_1.cs | 14 +- .../StackWalk/FrameHandling/FrameHelpers.cs | 2 +- .../StackWalk/GC/GcSignatureTypeProvider.cs | 16 +- .../ExtensionMethods.cs | 6 +- .../ClrDataFrame.cs | 10 +- .../ClrDataMethodDefinition.cs | 2 +- .../ClrDataMethodInstance.cs | 2 +- .../Dbi/DacDbiImpl.cs | 172 ++++++------- .../Dbi/Helpers/HeapWalk.cs | 2 +- .../Dbi/IDacDbiInterface.cs | 8 +- .../SOSDacImpl.IXCLRDataProcess.cs | 12 +- .../SOSDacImpl.cs | 52 ++-- .../SigFormat.cs | 22 +- .../TypeNameBuilder.cs | 34 +-- src/native/managed/cdac/gen/CdacGenerator.cs | 2 +- src/native/managed/cdac/gen/Emitter.cs | 10 +- .../cdac/gen/TypeNameResolverSource.cs | 8 +- .../DumpTests/AsyncContinuationDumpTests.cs | 6 +- .../cdac/tests/DumpTests/CCWDumpTests.cs | 6 +- .../DacDbi/DacDbiExactTypeHandleDumpTests.cs | 6 +- .../DumpTests/DacDbi/DacDbiLoaderDumpTests.cs | 2 +- .../DumpTests/DacDbi/DacDbiObjectDumpTests.cs | 14 +- .../IXCLRDataMethodDefinitionDumpTests.cs | 2 +- .../DumpTests/IXCLRDataValueDumpTests.cs | 2 +- .../DumpTests/ObjectiveCMarshalDumpTests.cs | 2 +- .../DumpTests/RuntimeTypeSystemDumpTests.cs | 46 ++-- .../cdac/tests/UnitTests/CodeVersionsTests.cs | 2 +- .../cdac/tests/UnitTests/DacDbiImplTests.cs | 8 +- .../cdac/tests/UnitTests/ExceptionTests.cs | 4 +- .../cdac/tests/UnitTests/MethodDescTests.cs | 4 +- .../cdac/tests/UnitTests/MethodTableTests.cs | 50 ++-- .../cdac/tests/UnitTests/ObjectTests.cs | 4 +- .../RuntimeMutableTypeSystemTests.cs | 20 +- .../tests/UnitTests/SOSDacInterface5Tests.cs | 2 +- .../cdac/tests/UnitTests/TypeDescTests.cs | 30 +-- 51 files changed, 536 insertions(+), 536 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs index 96f9c4be01aaa7..56fc9bb58a1fe0 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs @@ -31,8 +31,8 @@ public CdacTypeAttribute(params string[] names) public string[] Names { get; } /// - /// When true, the generator emits a TypeHandle(Target) - /// accessor that resolves the runtime TypeHandle by trying each + /// When true, the generator emits a ITypeHandle(Target) + /// accessor that resolves the runtime ITypeHandle by trying each /// candidate name against IManagedTypeSource. /// public bool HasTypeHandle { get; set; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs index 97154a6cbe0669..f81568d517512a 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs @@ -16,8 +16,8 @@ public interface IManagedTypeSource : IContract bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info) => throw new NotImplementedException(); Target.TypeInfo GetTypeInfo(string fullyQualifiedName) => throw new NotImplementedException(); - bool TryGetTypeHandle(string fullyQualifiedName, out TypeHandle typeHandle) => throw new NotImplementedException(); - TypeHandle GetTypeHandle(string fullyQualifiedName) => throw new NotImplementedException(); + bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle) => throw new NotImplementedException(); + ITypeHandle GetTypeHandle(string fullyQualifiedName) => throw new NotImplementedException(); bool TryGetStaticFieldAddress(string fullyQualifiedName, string fieldName, out TargetPointer address) => throw new NotImplementedException(); TargetPointer GetStaticFieldAddress(string fullyQualifiedName, string fieldName) => throw new NotImplementedException(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeMutableTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeMutableTypeSystem.cs index cecb94c10aeb81..2c77cbeeab8ffd 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeMutableTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeMutableTypeSystem.cs @@ -9,7 +9,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; public interface IRuntimeMutableTypeSystem : IContract { static string IContract.Name { get; } = nameof(RuntimeMutableTypeSystem); - IEnumerable EnumerateAddedFieldDescs(TypeHandle typeHandle, bool staticFields) => throw new NotImplementedException(); + IEnumerable EnumerateAddedFieldDescs(ITypeHandle typeHandle, bool staticFields) => throw new NotImplementedException(); bool IsFieldDescEnCNew(TargetPointer fieldDescPointer) => throw new NotImplementedException(); bool DoesEnCFieldDescNeedFixup(TargetPointer encFieldDescPointer) => throw new NotImplementedException(); TargetPointer GetEnCStaticFieldDataAddress(TargetPointer encFieldDescPointer) => throw new NotImplementedException(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index fc044825430e94..36a3952dcb7771 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -9,10 +9,10 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; // an opaque handle to a type handle. See IMetadata.GetMethodTableData -public readonly struct TypeHandle +public readonly struct ITypeHandle { // TODO-Layering: These members should be accessible only to contract implementations. - public TypeHandle(TargetPointer address) + public ITypeHandle(TargetPointer address) { Address = address; } @@ -70,7 +70,7 @@ public MethodDescHandle(TargetPointer address) public TargetPointer Address { get; } } -public readonly record struct TypedByRefInfo(TargetPointer Data, TargetPointer TypeHandle); +public readonly record struct TypedByRefInfo(TargetPointer Data, TargetPointer ITypeHandle); public enum ArrayFunctionType { @@ -143,121 +143,121 @@ public interface IRuntimeTypeSystem : IContract { static string IContract.Name => nameof(RuntimeTypeSystem); - #region TypeHandle inspection APIs - TypeHandle GetTypeHandle(TargetPointer address) => throw new NotImplementedException(); - TargetPointer GetModule(TypeHandle typeHandle) => throw new NotImplementedException(); - TargetPointer GetLoaderModule(TypeHandle typeHandle) => throw new NotImplementedException(); + #region ITypeHandle inspection APIs + ITypeHandle GetTypeHandle(TargetPointer address) => throw new NotImplementedException(); + TargetPointer GetModule(ITypeHandle typeHandle) => throw new NotImplementedException(); + TargetPointer GetLoaderModule(ITypeHandle typeHandle) => throw new NotImplementedException(); // A canonical method table is either the MethodTable itself, or in the case of a generic instantiation, it is the // MethodTable of the prototypical instance. - TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => throw new NotImplementedException(); + TargetPointer GetCanonicalMethodTable(ITypeHandle typeHandle) => throw new NotImplementedException(); // True if this MethodTable is the canonical MethodTable (i.e., EEClassOrCanonMT points directly to the EEClass) - bool IsCanonicalMethodTable(TypeHandle typeHandle) => throw new NotImplementedException(); - TargetPointer GetParentMethodTable(TypeHandle typeHandle) => throw new NotImplementedException(); + bool IsCanonicalMethodTable(ITypeHandle typeHandle) => throw new NotImplementedException(); + TargetPointer GetParentMethodTable(ITypeHandle typeHandle) => throw new NotImplementedException(); - TargetPointer GetMethodDescForSlot(TypeHandle methodTable, ushort slot) => throw new NotImplementedException(); - IEnumerable GetIntroducedMethodDescs(TypeHandle methodTable) => throw new NotImplementedException(); - TargetCodePointer GetSlot(TypeHandle typeHandle, uint slot) => throw new NotImplementedException(); + TargetPointer GetMethodDescForSlot(ITypeHandle methodTable, ushort slot) => throw new NotImplementedException(); + IEnumerable GetIntroducedMethodDescs(ITypeHandle methodTable) => throw new NotImplementedException(); + TargetCodePointer GetSlot(ITypeHandle typeHandle, uint slot) => throw new NotImplementedException(); - uint GetBaseSize(TypeHandle typeHandle) => throw new NotImplementedException(); - uint GetNumInstanceFieldBytes(TypeHandle typeHandle) => throw new NotImplementedException(); + uint GetBaseSize(ITypeHandle typeHandle) => throw new NotImplementedException(); + uint GetNumInstanceFieldBytes(ITypeHandle typeHandle) => throw new NotImplementedException(); // The component size is only available for strings and arrays. It is the size of the element type of the array, or the size of an ECMA 335 character (2 bytes) - uint GetComponentSize(TypeHandle typeHandle) => throw new NotImplementedException(); + uint GetComponentSize(ITypeHandle typeHandle) => throw new NotImplementedException(); // True if the MethodTable is the sentinel value associated with unallocated space in the managed heap - bool IsFreeObjectMethodTable(TypeHandle typeHandle) => throw new NotImplementedException(); + bool IsFreeObjectMethodTable(ITypeHandle 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(); + bool IsObject(ITypeHandle typeHandle) => throw new NotImplementedException(); + bool IsString(ITypeHandle typeHandle) => throw new NotImplementedException(); // True if the CorElementType represents a GC-collectable object reference. bool IsCorElementTypeObjRef(CorElementType elementType) => throw new NotImplementedException(); // Returns the address of one of the runtime's well-known singleton MethodTables, // or TargetPointer.Null if the runtime has not yet initialized that global. TargetPointer GetWellKnownMethodTable(WellKnownMethodTable kind) => throw new NotImplementedException(); // True if the MethodTable represents a type that contains managed references - bool ContainsGCPointers(TypeHandle typeHandle) => throw new NotImplementedException(); + bool ContainsGCPointers(ITypeHandle typeHandle) => throw new NotImplementedException(); // True if MethodTable represents a byreflike value (Span, ReadOnlySpan, etc.). - bool IsByRefLike(TypeHandle typeHandle) => throw new NotImplementedException(); + bool IsByRefLike(ITypeHandle typeHandle) => throw new NotImplementedException(); // If the type is an HFA (or HVA on ARM64), returns true and sets elementSize // to 4, 8, or 16. Returns false otherwise (including on targets that don't // define FEATURE_HFA). Mirrors MethodTable::GetHFAType in // src/coreclr/vm/class.cpp. - bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize) => throw new NotImplementedException(); + bool TryGetHFAElementSize(ITypeHandle typeHandle, out int elementSize) => throw new NotImplementedException(); // True if the type requires 8-byte alignment on platforms that don't 8-byte align by default (FEATURE_64BIT_ALIGNMENT) - bool RequiresAlign8(TypeHandle typeHandle) => throw new NotImplementedException(); + bool RequiresAlign8(ITypeHandle typeHandle) => throw new NotImplementedException(); // Returns the cached SystemV AMD64 eightbyte register-passing classification for a value type // (used to decide how a struct is passed in registers), or false if the type has no such // classification (not applicable, or the runtime was not built with UNIX_AMD64_ABI). Mirrors // the EEClass::GetSystemVAmd64EightByteInfo runtime data used by the JIT. - bool TryGetSystemVAmd64EightByteClassification(TypeHandle typeHandle, out SystemVAmd64EightByteClassification classification) => throw new NotImplementedException(); + bool TryGetSystemVAmd64EightByteClassification(ITypeHandle typeHandle, out SystemVAmd64EightByteClassification classification) => throw new NotImplementedException(); // True if the MethodTable represents a continuation subtype that has no metadata of its own - bool IsContinuationWithoutMetadata(TypeHandle typeHandle) => throw new NotImplementedException(); + bool IsContinuationWithoutMetadata(ITypeHandle typeHandle) => throw new NotImplementedException(); /// /// Enumerates GC pointer runs from the CGCDesc stored before the method table. /// Returns (offset, size) pairs normalized to actual byte lengths. /// See RuntimeTypeSystem.md for the full GCDesc format documentation. /// - IEnumerable<(uint Offset, uint Size)> GetGCDescSeries(TypeHandle typeHandle, uint numComponents = 0) => throw new NotImplementedException(); - bool IsDynamicStatics(TypeHandle typeHandle) => throw new NotImplementedException(); - ushort GetNumInterfaces(TypeHandle typeHandle) => throw new NotImplementedException(); + IEnumerable<(uint Offset, uint Size)> GetGCDescSeries(ITypeHandle typeHandle, uint numComponents = 0) => throw new NotImplementedException(); + bool IsDynamicStatics(ITypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumInterfaces(ITypeHandle 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 GetNumVtableSlots(TypeHandle typeHandle) => throw new NotImplementedException(); - ushort GetNumMethods(TypeHandle typeHandle) => throw new NotImplementedException(); + uint GetTypeDefToken(ITypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumVtableSlots(ITypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumMethods(ITypeHandle 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(); - IEnumerable GetFieldDescList(TypeHandle typeHandle) => throw new NotImplementedException(); + uint GetTypeDefTypeAttributes(ITypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumInstanceFields(ITypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumStaticFields(ITypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumThreadStaticFields(ITypeHandle typeHandle) => throw new NotImplementedException(); + IEnumerable GetFieldDescList(ITypeHandle typeHandle) => throw new NotImplementedException(); // True if the MethodTable represents a type tracked as an Objective-C reference type with a finalizer - bool IsTrackedReferenceWithFinalizer(TypeHandle typeHandle) => throw new NotImplementedException(); - TargetPointer GetGCStaticsBasePointer(TypeHandle typeHandle) => throw new NotImplementedException(); - TargetPointer GetNonGCStaticsBasePointer(TypeHandle typeHandle) => throw new NotImplementedException(); - TargetPointer GetGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr) => throw new NotImplementedException(); - TargetPointer GetNonGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr) => throw new NotImplementedException(); + bool IsTrackedReferenceWithFinalizer(ITypeHandle typeHandle) => throw new NotImplementedException(); + TargetPointer GetGCStaticsBasePointer(ITypeHandle typeHandle) => throw new NotImplementedException(); + TargetPointer GetNonGCStaticsBasePointer(ITypeHandle typeHandle) => throw new NotImplementedException(); + TargetPointer GetGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) => throw new NotImplementedException(); + TargetPointer GetNonGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) => throw new NotImplementedException(); - ReadOnlySpan GetInstantiation(TypeHandle typeHandle) => throw new NotImplementedException(); - public bool IsClassInited(TypeHandle typeHandle) => throw new NotImplementedException(); - public bool IsInitError(TypeHandle typeHandle) => throw new NotImplementedException(); - bool IsGenericTypeDefinition(TypeHandle typeHandle) => throw new NotImplementedException(); - bool ContainsGenericVariables(TypeHandle typeHandle) => throw new NotImplementedException(); - bool IsCollectible(TypeHandle typeHandle) => throw new NotImplementedException(); + ReadOnlySpan GetInstantiation(ITypeHandle typeHandle) => throw new NotImplementedException(); + public bool IsClassInited(ITypeHandle typeHandle) => throw new NotImplementedException(); + public bool IsInitError(ITypeHandle typeHandle) => throw new NotImplementedException(); + bool IsGenericTypeDefinition(ITypeHandle typeHandle) => throw new NotImplementedException(); + bool ContainsGenericVariables(ITypeHandle typeHandle) => throw new NotImplementedException(); + bool IsCollectible(ITypeHandle typeHandle) => throw new NotImplementedException(); - bool HasTypeParam(TypeHandle typeHandle) => throw new NotImplementedException(); + bool HasTypeParam(ITypeHandle typeHandle) => throw new NotImplementedException(); // Element type of the type. NOTE: this drops the CorElementType.GenericInst, and CorElementType.String is returned as CorElementType.Class. // If this returns CorElementType.ValueType it may be a normal valuetype or a "NATIVE" valuetype used to represent an interop view on a structure // HasTypeParam will return true for cases where this is the interop view - CorElementType GetSignatureCorElementType(TypeHandle typeHandle) => throw new NotImplementedException(); - bool IsValueType(TypeHandle typeHandle) => throw new NotImplementedException(); + CorElementType GetSignatureCorElementType(ITypeHandle typeHandle) => throw new NotImplementedException(); + bool IsValueType(ITypeHandle typeHandle) => throw new NotImplementedException(); // Internal element type of the type. Unlike GetSignatureCorElementType, this returns the underlying primitive // type for enums (e.g. I4 for an enum with int underlying type) and for PrimitiveValueType categories. // For arrays, reference types, and TypeDescs, behaves identically to GetSignatureCorElementType. - CorElementType GetInternalCorElementType(TypeHandle typeHandle) => throw new NotImplementedException(); - - // return true if the TypeHandle represents an enum type. - bool IsEnum(TypeHandle typeHandle) => throw new NotImplementedException(); - - // return true if the TypeHandle represents a delegate type (i.e., its parent is System.MulticastDelegate) - bool IsDelegate(TypeHandle typeHandle) => throw new NotImplementedException(); - - // return true if the TypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. - bool IsArray(TypeHandle typeHandle, out uint rank) => throw new NotImplementedException(); - TypeHandle GetTypeParam(TypeHandle typeHandle) => throw new NotImplementedException(); - TypeHandle GetConstructedType(TypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default) => throw new NotImplementedException(); - TypeHandle GetPrimitiveType(CorElementType typeCode) => throw new NotImplementedException(); - bool IsGenericVariable(TypeHandle typeHandle, out TargetPointer module, out uint token) => throw new NotImplementedException(); - bool IsFunctionPointer(TypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) => throw new NotImplementedException(); - bool IsPointer(TypeHandle typeHandle) => throw new NotImplementedException(); - bool IsTypeDesc(TypeHandle typeHandle) => throw new NotImplementedException(); + CorElementType GetInternalCorElementType(ITypeHandle typeHandle) => throw new NotImplementedException(); + + // return true if the ITypeHandle represents an enum type. + bool IsEnum(ITypeHandle typeHandle) => throw new NotImplementedException(); + + // return true if the ITypeHandle represents a delegate type (i.e., its parent is System.MulticastDelegate) + bool IsDelegate(ITypeHandle typeHandle) => throw new NotImplementedException(); + + // return true if the ITypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. + bool IsArray(ITypeHandle typeHandle, out uint rank) => throw new NotImplementedException(); + ITypeHandle GetTypeParam(ITypeHandle typeHandle) => throw new NotImplementedException(); + ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default) => throw new NotImplementedException(); + ITypeHandle GetPrimitiveType(CorElementType typeCode) => throw new NotImplementedException(); + bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token) => throw new NotImplementedException(); + bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) => throw new NotImplementedException(); + bool IsPointer(ITypeHandle typeHandle) => throw new NotImplementedException(); + bool IsTypeDesc(ITypeHandle typeHandle) => throw new NotImplementedException(); TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) => throw new NotImplementedException(); - // Returns null if the TypeHandle is not a class/struct/generic variable - #endregion TypeHandle inspection APIs + // Returns null if the ITypeHandle is not a class/struct/generic variable + #endregion ITypeHandle inspection APIs #region MethodDesc inspection APIs MethodDescHandle GetMethodDescHandle(TargetPointer targetPointer) => throw new NotImplementedException(); @@ -265,7 +265,7 @@ public interface IRuntimeTypeSystem : IContract // Return true for an uninstantiated generic method bool IsGenericMethodDefinition(MethodDescHandle methodDesc) => throw new NotImplementedException(); - ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDesc) => throw new NotImplementedException(); + ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDesc) => throw new NotImplementedException(); GenericContextLoc GetGenericContextLoc(MethodDescHandle methodDescHandle) => throw new NotImplementedException(); @@ -336,9 +336,9 @@ public interface IRuntimeTypeSystem : IContract bool IsFieldDescRVA(TargetPointer fieldDescPointer) => throw new NotImplementedException(); CorElementType GetFieldDescType(TargetPointer fieldDescPointer) => throw new NotImplementedException(); uint GetFieldDescOffset(TargetPointer fieldDescPointer, FieldDefinition? fieldDef) => throw new NotImplementedException(); - TypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) => throw new NotImplementedException(); + ITypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) => throw new NotImplementedException(); bool TryGetFieldDescNext(TargetPointer fieldDescPointer, out TargetPointer nextFieldDesc) => throw new NotImplementedException(); - TargetPointer GetFieldDescByName(TypeHandle typeHandle, string fieldName) => throw new NotImplementedException(); + TargetPointer GetFieldDescByName(ITypeHandle typeHandle, string fieldName) => throw new NotImplementedException(); TargetPointer GetFieldDescStaticAddress(TargetPointer fieldDescPointer, bool unboxValueTypes = true) => throw new NotImplementedException(); TargetPointer GetFieldDescThreadStaticAddress(TargetPointer fieldDescPointer, TargetPointer thread, bool unboxValueTypes = true) => throw new NotImplementedException(); #endregion FieldDesc inspection APIs diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs index e32b595f5f4b32..f07ed2b07ad8c9 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs @@ -9,7 +9,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; public interface ISignature : IContract { static string IContract.Name { get; } = nameof(Signature); - TypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, TypeHandle ctx) => throw new NotImplementedException(); + ITypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) => throw new NotImplementedException(); TargetPointer GetVarArgArgsBase(TargetPointer vaSigCookieAddr) => throw new NotImplementedException(); void GetVarArgSignature(TargetPointer vaSigCookieAddr, out TargetPointer signatureAddress, out uint signatureLength) => throw new NotImplementedException(); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs index 633369d4f18bd8..ca99c4d33f3e1a 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs @@ -154,7 +154,7 @@ bool ICodeVersions.CodeVersionManagerSupportsMethod(TargetPointer methodDescAddr if (rts.IsCollectibleMethod(md)) return false; TargetPointer mtAddr = rts.GetMethodTable(md); - TypeHandle mt = rts.GetTypeHandle(mtAddr); + ITypeHandle mt = rts.GetTypeHandle(mtAddr); TargetPointer modAddr = rts.GetModule(mt); ILoader loader = _target.Contracts.Loader; ModuleHandle mod = loader.GetModuleHandleFromModulePtr(modAddr); @@ -342,7 +342,7 @@ private void GetModuleAndMethodDesc(TargetPointer methodDesc, out TargetPointer IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; MethodDescHandle md = rts.GetMethodDescHandle(methodDesc); TargetPointer mtAddr = rts.GetMethodTable(md); - TypeHandle typeHandle = rts.GetTypeHandle(mtAddr); + ITypeHandle typeHandle = rts.GetTypeHandle(mtAddr); module = rts.GetModule(typeHandle); methodDefToken = rts.GetMethodToken(md); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs index 843d96a31f4792..937ee347a0d132 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs @@ -144,7 +144,7 @@ public List GetMOWs(TargetPointer obj, out bool hasMOWTable) public bool IsComWrappersRCW(TargetPointer rcw) { TargetPointer mt = _target.Contracts.Object.GetMethodTableAddress(rcw); - return mt == Data.NativeObjectWrapper.TypeHandle(_target).Address; + return mt == Data.NativeObjectWrapper.ITypeHandle(_target).Address; } public TargetPointer GetComWrappersRCWForObject(TargetPointer obj) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ConditionalWeakTable_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ConditionalWeakTable_1.cs index 90ecfdd452a60c..8c1931d72becea 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ConditionalWeakTable_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ConditionalWeakTable_1.cs @@ -34,7 +34,7 @@ bool IConditionalWeakTable.TryGetValue(TargetPointer conditionalWeakTable, Targe Data.Array entriesArray = _target.ProcessedData.GetOrAdd(container.Entries); TargetPointer entriesMT = _target.Contracts.Object.GetMethodTableAddress(container.Entries); - TypeHandle entriesTypeHandle = _target.Contracts.RuntimeTypeSystem.GetTypeHandle(entriesMT); + ITypeHandle entriesTypeHandle = _target.Contracts.RuntimeTypeSystem.GetTypeHandle(entriesMT); uint entrySize = _target.Contracts.RuntimeTypeSystem.GetComponentSize(entriesTypeHandle); while (entriesIndex != -1) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Exception_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Exception_1.cs index 217f185ecb0b80..771b06e02967d4 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Exception_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Exception_1.cs @@ -63,7 +63,7 @@ IEnumerable IException.GetExceptionStackFrames(TargetPo TargetPointer mt = objectContract.GetMethodTableAddress(stackTraceObj); if (mt == TargetPointer.Null) throw new InvalidOperationException($"Stack trace object 0x{stackTraceObj.Value:x} has no MethodTable."); - TypeHandle stackTraceHandle = rtsContract.GetTypeHandle(mt); + ITypeHandle stackTraceHandle = rtsContract.GetTypeHandle(mt); TargetPointer i1ArrayAddr; if (rtsContract.ContainsGCPointers(stackTraceHandle)) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs index ca02cbf7f3bfcf..e9245453fbaa07 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs @@ -552,7 +552,7 @@ List IExecutionManager.GetExceptionClauses(CodeBlockHandle IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; MethodDescHandle mdHandle = rts.GetMethodDescHandle(methodDescPtr); TargetPointer mtPtr = rts.GetMethodTable(mdHandle); - TypeHandle th = rts.GetTypeHandle(mtPtr); + ITypeHandle th = rts.GetTypeHandle(mtPtr); TargetPointer handleModuleAddr = rts.GetModule(th); List exceptionClauses = new List(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs index a2987a89297a8f..fabb056bfecac2 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs @@ -14,7 +14,7 @@ internal sealed class ManagedTypeSource_1 : IManagedTypeSource { private readonly Target _target; private readonly Dictionary _typeInfoCache = new(); - private readonly Dictionary _typeHandleCache = new(); + private readonly Dictionary _typeHandleCache = new(); private readonly Dictionary<(string Fqn, string FieldName), TargetPointer> _fieldDescCache = new(); private bool _inSearch; @@ -81,22 +81,22 @@ public bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info) } } - public TypeHandle GetTypeHandle(string fullyQualifiedName) + public ITypeHandle GetTypeHandle(string fullyQualifiedName) { - if (!TryGetTypeHandle(fullyQualifiedName, out TypeHandle typeHandle)) + if (!TryGetTypeHandle(fullyQualifiedName, out ITypeHandle typeHandle)) throw new InvalidOperationException($"Managed type '{fullyQualifiedName}' is not resolvable through {nameof(ManagedTypeSource_1)}."); return typeHandle; } - public bool TryGetTypeHandle(string fullyQualifiedName, out TypeHandle typeHandle) + public bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle) { if (_typeHandleCache.TryGetValue(fullyQualifiedName, out typeHandle)) return !typeHandle.IsNull; if (!TryResolveType(fullyQualifiedName, out typeHandle, out _, out _)) { - _typeHandleCache[fullyQualifiedName] = new TypeHandle(TargetPointer.Null); + _typeHandleCache[fullyQualifiedName] = new ITypeHandle(TargetPointer.Null); return false; } @@ -128,7 +128,7 @@ public bool TryGetStaticFieldAddress(string fullyQualifiedName, string fieldName // Gate on the statics base being allocated for the enclosing class so callers cannot // dereference a small offset-from-zero when the class has not been initialized. TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fieldDescAddr); - TypeHandle ctx = rts.GetTypeHandle(enclosingMT); + ITypeHandle ctx = rts.GetTypeHandle(enclosingMT); CorElementType type = rts.GetFieldDescType(fieldDescAddr); bool isGC = type is CorElementType.Class or CorElementType.ValueType; TargetPointer @base = isGC ? rts.GetGCStaticsBasePointer(ctx) : rts.GetNonGCStaticsBasePointer(ctx); @@ -163,7 +163,7 @@ public bool TryGetThreadStaticFieldAddress(string fullyQualifiedName, string fie // cannot dereference a small offset-from-zero when this thread has not initialized // thread-static storage for the type. TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fieldDescAddr); - TypeHandle ctx = rts.GetTypeHandle(enclosingMT); + ITypeHandle ctx = rts.GetTypeHandle(enclosingMT); CorElementType type = rts.GetFieldDescType(fieldDescAddr); bool isGC = type is CorElementType.Class or CorElementType.ValueType; TargetPointer @base = isGC @@ -182,7 +182,7 @@ private bool TryGetFieldDesc(string fullyQualifiedName, string fieldName, out Ta if (_fieldDescCache.TryGetValue(key, out fieldDescAddr)) return fieldDescAddr != TargetPointer.Null; - if (!TryResolveType(fullyQualifiedName, out TypeHandle th, out _, out _)) + if (!TryResolveType(fullyQualifiedName, out ITypeHandle th, out _, out _)) { fieldDescAddr = TargetPointer.Null; _fieldDescCache[key] = TargetPointer.Null; @@ -198,7 +198,7 @@ private bool TryBuildTypeInfo(string managedFqName, out Target.TypeInfo info) { info = default; - if (!TryResolveType(managedFqName, out TypeHandle th, out MetadataReader? mdReader, out TypeDefinition typeDef)) + if (!TryResolveType(managedFqName, out ITypeHandle th, out MetadataReader? mdReader, out TypeDefinition typeDef)) return false; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; @@ -246,9 +246,9 @@ private bool TryBuildTypeInfo(string managedFqName, out Target.TypeInfo info) return true; } - private bool TryResolveType(string managedFqName, out TypeHandle th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef) + private bool TryResolveType(string managedFqName, out ITypeHandle th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef) { - th = new TypeHandle(TargetPointer.Null); + th = new ITypeHandle(TargetPointer.Null); typeDef = default; ILoader loader = _target.Contracts.Loader; @@ -264,7 +264,7 @@ private bool TryResolveType(string managedFqName, out TypeHandle th, [NotNullWhe if (!TryFindTypeDefinition(moduleHandle, managedFqName, out mdReader, out TypeDefinitionHandle typeDefHandle)) return false; - // Look up the runtime TypeHandle via the module's TypeDef → MethodTable map. + // Look up the runtime ITypeHandle via the module's TypeDef → MethodTable map. int token = MetadataTokens.GetToken((EntityHandle)typeDefHandle); TargetPointer typeDefToMethodTable = loader.GetLookupTables(moduleHandle).TypeDefToMethodTable; TargetPointer typeHandlePtr = loader.GetModuleLookupMapElement(typeDefToMethodTable, (uint)token, out _); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Object_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Object_1.cs index 54a5cec221efff..59e3e73206f51c 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Object_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Object_1.cs @@ -74,7 +74,7 @@ public TargetPointer GetArrayData(TargetPointer address, out uint count, out Tar if (mt == TargetPointer.Null) throw new ArgumentException("Address represents a set-free object"); Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem; - TypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt); + ITypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt); uint rank; if (!typeSystemContract.IsArray(typeHandle, out rank)) throw new ArgumentException("Address does not represent an array object", nameof(address)); @@ -214,7 +214,7 @@ public ulong GetSize(TargetPointer address) if (mt == TargetPointer.Null) throw new ArgumentException("Address represents a free object"); Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem; - TypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt); + ITypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt); ulong size = typeSystemContract.GetBaseSize(typeHandle); uint componentSize = typeSystemContract.GetComponentSize(typeHandle); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeMutableTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeMutableTypeSystem_1.cs index c58e5ef4a58b59..b997b35d46c390 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeMutableTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeMutableTypeSystem_1.cs @@ -26,7 +26,7 @@ bool IRuntimeMutableTypeSystem.IsFieldDescEnCNew(TargetPointer fieldDescPointer) return offset == _target.ReadGlobal(Constants.Globals.FieldOffsetNewEnc); } - IEnumerable IRuntimeMutableTypeSystem.EnumerateAddedFieldDescs(TypeHandle typeHandle, bool staticFields) + IEnumerable IRuntimeMutableTypeSystem.EnumerateAddedFieldDescs(ITypeHandle typeHandle, bool staticFields) { // Only MethodTable type handles can have EnC-added fields. TypeDescs (TypeVar, FnPtr, etc.) cannot. if (!typeHandle.IsMethodTable()) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index ad95b49db1ec0f..b8e2e369bdbc0d 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -31,7 +31,7 @@ internal partial struct RuntimeTypeSystem_1 : IRuntimeTypeSystem // If we need to invalidate our view of memory, we should clear this dictionary. private readonly Dictionary _methodTables = new(); private readonly Dictionary _methodDescs = new(); - private readonly Dictionary _typeHandles = new(); + private readonly Dictionary _typeHandles = new(); public void Flush(FlushScope scope) { @@ -73,23 +73,23 @@ internal MethodTable(Data.MethodTable data) private readonly struct TypeKey : IEquatable { - public TypeKey(TypeHandle typeHandle, CorElementType elementType, int rank, ImmutableArray typeArgs, SignatureCallingConvention callConv = SignatureCallingConvention.Default) + public TypeKey(ITypeHandle typeHandle, CorElementType elementType, int rank, ImmutableArray typeArgs, SignatureCallingConvention callConv = SignatureCallingConvention.Default) { - TypeHandle = typeHandle; + ITypeHandle = typeHandle; ElementType = elementType; Rank = rank; TypeArgs = typeArgs; CallConv = callConv; } - public TypeHandle TypeHandle { get; } + public ITypeHandle ITypeHandle { get; } public CorElementType ElementType { get; } public int Rank { get; } - public ImmutableArray TypeArgs { get; } + public ImmutableArray TypeArgs { get; } public SignatureCallingConvention CallConv { get; } public bool Equals(TypeKey other) { - if (ElementType != other.ElementType || Rank != other.Rank || CallConv != other.CallConv || TypeArgs.Length != other.TypeArgs.Length || !TypeHandle.Equals(other.TypeHandle)) + if (ElementType != other.ElementType || Rank != other.Rank || CallConv != other.CallConv || TypeArgs.Length != other.TypeArgs.Length || !ITypeHandle.Equals(other.ITypeHandle)) return false; for (int i = 0; i < TypeArgs.Length; i++) { @@ -103,8 +103,8 @@ public bool Equals(TypeKey other) public override int GetHashCode() { - int hash = HashCode.Combine(TypeHandle.GetHashCode(), (int)ElementType, Rank, (int)CallConv); - foreach (TypeHandle th in TypeArgs) + int hash = HashCode.Combine(ITypeHandle.GetHashCode(), (int)ElementType, Rank, (int)CallConv); + foreach (ITypeHandle th in TypeArgs) { hash = HashCode.Combine(hash, th.GetHashCode()); } @@ -112,7 +112,7 @@ public override int GetHashCode() } } - // Low order bits of TypeHandle address. + // Low order bits of ITypeHandle address. // If the low bits contain a 2, then it is a TypeDesc [Flags] internal enum TypeHandleBits @@ -353,11 +353,11 @@ private InstantiatedMethodDesc(Target target, TargetPointer methodDescPointer) TargetPointer perInstInfo = _desc.PerInstInfo; if ((perInstInfo == TargetPointer.Null) || (numGenericArgs == 0)) { - Instantiation = System.Array.Empty(); + Instantiation = System.Array.Empty(); } else { - Instantiation = new TypeHandle[numGenericArgs]; + Instantiation = new ITypeHandle[numGenericArgs]; for (int i = 0; i < numGenericArgs; i++) { Instantiation[i] = rts.GetTypeHandle(target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)i)); @@ -370,7 +370,7 @@ private InstantiatedMethodDesc(Target target, TargetPointer methodDescPointer) internal bool IsGenericMethodDefinition => HasFlags(InstantiatedMethodDescFlags2.KindMask, InstantiatedMethodDescFlags2.GenericMethodDefinition); internal bool HasPerInstInfo => _desc.PerInstInfo != TargetPointer.Null; internal bool HasMethodInstantiation => IsGenericMethodDefinition || HasPerInstInfo; - public TypeHandle[] Instantiation { get; } + public ITypeHandle[] Instantiation { get; } } private sealed class DynamicMethodDesc : IData @@ -464,7 +464,7 @@ internal TargetPointer ContinuationSingletonEEClassPointer internal ulong MethodDescAlignment => _methodDescAlignment; - public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) + public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) { TypeHandleBits addressLowBits = (TypeHandleBits)((ulong)typeHandlePointer & ((ulong)_target.PointerSize - 1)); @@ -476,14 +476,14 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) // if we already validated this address, return a handle if (_methodTables.ContainsKey(typeHandlePointer)) { - return new TypeHandle(typeHandlePointer); + return new ITypeHandle(typeHandlePointer); } // Check for a TypeDesc if (addressLowBits == TypeHandleBits.TypeDesc) { // This is a TypeDesc - return new TypeHandle(typeHandlePointer); + return new ITypeHandle(typeHandlePointer); } TargetPointer methodTablePointer = typeHandlePointer; @@ -494,7 +494,7 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) // we already cached the data, we must have validated the address, create the representation struct for our use MethodTable trustedMethodTable = new MethodTable(methodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTable); - return new TypeHandle(methodTablePointer); + return new ITypeHandle(methodTablePointer); } // If it's the free object method table, we trust it to be valid @@ -503,7 +503,7 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) Data.MethodTable freeObjectMethodTableData = _target.ProcessedData.GetOrAdd(methodTablePointer); MethodTable trustedMethodTable = new MethodTable(freeObjectMethodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTable); - return new TypeHandle(methodTablePointer); + return new ITypeHandle(methodTablePointer); } // Otherwse, get ready to validate @@ -515,9 +515,9 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) Data.MethodTable trustedMethodTableData = _target.ProcessedData.GetOrAdd(methodTablePointer); MethodTable trustedMethodTableF = new MethodTable(trustedMethodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTableF); - return new TypeHandle(methodTablePointer); + return new ITypeHandle(methodTablePointer); } - public TargetPointer GetModule(TypeHandle typeHandle) + public TargetPointer GetModule(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -544,17 +544,17 @@ public TargetPointer GetModule(TypeHandle typeHandle) return TargetPointer.Null; } } - public TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable; - public bool IsCanonicalMethodTable(TypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].IsCanonMT; - public TargetPointer GetParentMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[typeHandle.Address].ParentMethodTable; + public TargetPointer GetCanonicalMethodTable(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable; + public bool IsCanonicalMethodTable(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].IsCanonMT; + public TargetPointer GetParentMethodTable(ITypeHandle 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 GetBaseSize(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.BaseSize; - public uint GetNumInstanceFieldBytes(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.BaseSize - GetClassData(typeHandle).BaseSizePadding; + public uint GetNumInstanceFieldBytes(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.BaseSize - GetClassData(typeHandle).BaseSizePadding; - public uint GetComponentSize(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.ComponentSize; + public uint GetComponentSize(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.ComponentSize; - private TargetPointer GetClassPointer(TypeHandle typeHandle) + private TargetPointer GetClassPointer(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -565,7 +565,7 @@ private TargetPointer GetClassPointer(TypeHandle typeHandle) return methodTable.EEClassOrCanonMT; case MethodTableFlags_1.EEClassOrCanonMTBits.CanonMT: TargetPointer canonMTPtr = MethodTableFlags_1.UntagEEClassOrCanonMT(methodTable.EEClassOrCanonMT); - TypeHandle canonMTHandle = GetTypeHandle(canonMTPtr); + ITypeHandle canonMTHandle = GetTypeHandle(canonMTPtr); MethodTable canonMT = _methodTables[canonMTHandle.Address]; return canonMT.EEClassOrCanonMT; // canonical method table EEClassOrCanonMT is always EEClass default: @@ -573,7 +573,7 @@ private TargetPointer GetClassPointer(TypeHandle typeHandle) } } - public bool TryGetSystemVAmd64EightByteClassification(TypeHandle typeHandle, out SystemVAmd64EightByteClassification classification) + public bool TryGetSystemVAmd64EightByteClassification(ITypeHandle typeHandle, out SystemVAmd64EightByteClassification classification) { classification = default; @@ -605,18 +605,18 @@ public bool TryGetSystemVAmd64EightByteClassification(TypeHandle typeHandle, out } // only called on validated method tables, so we don't need to re-validate the EEClass - private Data.EEClass GetClassData(TypeHandle typeHandle) + private Data.EEClass GetClassData(ITypeHandle typeHandle) { TargetPointer clsPtr = GetClassPointer(typeHandle); return _target.ProcessedData.GetOrAdd(clsPtr); } - public bool IsFreeObjectMethodTable(TypeHandle typeHandle) => FreeObjectMethodTablePointer == typeHandle.Address; + public bool IsFreeObjectMethodTable(ITypeHandle typeHandle) => FreeObjectMethodTablePointer == typeHandle.Address; - public bool IsObject(TypeHandle typeHandle) => ObjectMethodTablePointer != TargetPointer.Null && ObjectMethodTablePointer == typeHandle.Address; + public bool IsObject(ITypeHandle typeHandle) => ObjectMethodTablePointer != TargetPointer.Null && ObjectMethodTablePointer == typeHandle.Address; - public bool IsString(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsString; + public bool IsString(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsString; public bool IsCorElementTypeObjRef(CorElementType elementType) => elementType is CorElementType.Class @@ -645,8 +645,8 @@ public TargetPointer GetWellKnownMethodTable(WellKnownMethodTable kind) return value; } - public bool ContainsGCPointers(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.ContainsGCPointers; - public bool IsByRefLike(TypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsByRefLike; + public bool ContainsGCPointers(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.ContainsGCPointers; + public bool IsByRefLike(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsByRefLike; private bool IsFeatureHfaTarget(out RuntimeInfoArchitecture arch) { @@ -654,7 +654,7 @@ private bool IsFeatureHfaTarget(out RuntimeInfoArchitecture arch) return arch is RuntimeInfoArchitecture.Arm or RuntimeInfoArchitecture.Arm64; } - public bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize) + public bool TryGetHFAElementSize(ITypeHandle typeHandle, out int elementSize) { elementSize = 0; @@ -673,7 +673,7 @@ public bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize) return true; } - TypeHandle current = typeHandle; + ITypeHandle current = typeHandle; for (int depth = 0; depth < 16; depth++) { int vectorElem = GetVectorHFAElementSize(current); @@ -719,7 +719,7 @@ public bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize) // Mirrors MethodTable::GetVectorHFA in src/coreclr/vm/class.cpp. Any // metadata decode failure returns 0 (treated as "not an HVA"). - private int GetVectorHFAElementSize(TypeHandle typeHandle) + private int GetVectorHFAElementSize(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable() || !_methodTables[typeHandle.Address].Flags.IsIntrinsicType) return 0; @@ -773,7 +773,7 @@ private int GetVectorHFAElementSize(TypeHandle typeHandle) if (elemSize == 0) return 0; - ReadOnlySpan instantiation = ((IRuntimeTypeSystem)this).GetInstantiation(typeHandle); + ReadOnlySpan instantiation = ((IRuntimeTypeSystem)this).GetInstantiation(typeHandle); if (instantiation.Length < 1) return 0; @@ -794,14 +794,14 @@ private static bool IsCorNumericalType(CorElementType t) => (t >= CorElementType.I1 && t <= CorElementType.R8) || t == CorElementType.I || t == CorElementType.U; - public bool RequiresAlign8(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.RequiresAlign8; - public bool IsContinuationWithoutMetadata(TypeHandle typeHandle) => typeHandle.IsMethodTable() + public bool RequiresAlign8(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.RequiresAlign8; + public bool IsContinuationWithoutMetadata(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && ContinuationMethodTablePointer != TargetPointer.Null && _methodTables[typeHandle.Address].ParentMethodTable == ContinuationMethodTablePointer && ContinuationSingletonEEClassPointer != TargetPointer.Null && GetClassPointer(typeHandle) == ContinuationSingletonEEClassPointer; - IEnumerable<(uint Offset, uint Size)> IRuntimeTypeSystem.GetGCDescSeries(TypeHandle typeHandle, uint numComponents) + IEnumerable<(uint Offset, uint Size)> IRuntimeTypeSystem.GetGCDescSeries(ITypeHandle typeHandle, uint numComponents) { if (!typeHandle.IsMethodTable()) yield break; @@ -875,17 +875,17 @@ public bool IsContinuationWithoutMetadata(TypeHandle typeHandle) => typeHandle.I } } - 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 bool IsDynamicStatics(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsDynamicStatics; + public ushort GetNumInterfaces(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : _methodTables[typeHandle.Address].NumInterfaces; - public uint GetTypeDefToken(TypeHandle typeHandle) + public uint GetTypeDefToken(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return 0; MethodTable methodTable = _methodTables[typeHandle.Address]; return (uint)(methodTable.Flags.GetTypeDefRid() | ((int)TableIndex.TypeDef << 24)); } - public ushort GetNumVtableSlots(TypeHandle typeHandle) + public ushort GetNumVtableSlots(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return 0; @@ -893,12 +893,12 @@ public ushort GetNumVtableSlots(TypeHandle typeHandle) ushort numNonVirtualSlots = methodTable.IsCanonMT ? GetClassData(typeHandle).NumNonVirtualSlots : (ushort)0; return checked((ushort)(methodTable.NumVirtuals + numNonVirtualSlots)); } - public ushort GetNumMethods(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumMethods; - 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 IEnumerable GetFieldDescList(TypeHandle typeHandle) + public ushort GetNumMethods(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumMethods; + public uint GetTypeDefTypeAttributes(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : GetClassData(typeHandle).CorTypeAttr; + public ushort GetNumInstanceFields(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields; + public ushort GetNumStaticFields(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields; + public ushort GetNumThreadStaticFields(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields; + public IEnumerable GetFieldDescList(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) yield break; @@ -921,14 +921,14 @@ public IEnumerable GetFieldDescList(TypeHandle typeHandle) TargetPointer parentMT = GetParentMethodTable(typeHandle); if (parentMT != TargetPointer.Null) { - TypeHandle parentHandle = GetTypeHandle(parentMT); + ITypeHandle parentHandle = GetTypeHandle(parentMT); numInstanceFields -= GetNumInstanceFields(parentHandle); } int totalFields = numInstanceFields + GetNumStaticFields(typeHandle); return (fieldDescListPtr, fieldDescSize, totalFields); } - public bool IsTrackedReferenceWithFinalizer(TypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsTrackedReferenceWithFinalizer; - private TargetPointer GetDynamicStaticsInfo(TypeHandle typeHandle) + public bool IsTrackedReferenceWithFinalizer(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsTrackedReferenceWithFinalizer; + private TargetPointer GetDynamicStaticsInfo(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return default; @@ -941,7 +941,7 @@ private TargetPointer GetDynamicStaticsInfo(TypeHandle typeHandle) return dynamicStaticsInfoAddr; } - private Data.ThreadStaticsInfo GetThreadStaticsInfo(TypeHandle typeHandle) + private Data.ThreadStaticsInfo GetThreadStaticsInfo(ITypeHandle typeHandle) { MethodTable methodTable = _methodTables[typeHandle.Address]; TargetPointer threadStaticsInfoSize = _target.GetTypeInfo(DataType.ThreadStaticsInfo).Size!.Value; @@ -950,7 +950,7 @@ private Data.ThreadStaticsInfo GetThreadStaticsInfo(TypeHandle typeHandle) return threadStaticsInfo; } - public TargetPointer GetGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr) + public TargetPointer GetGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -959,7 +959,7 @@ public TargetPointer GetGCThreadStaticsBasePointer(TypeHandle typeHandle, Target return threadContract.GetThreadLocalStaticBase(threadPtr, tlsIndexPtr); } - public TargetPointer GetNonGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr) + public TargetPointer GetNonGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -968,7 +968,7 @@ public TargetPointer GetNonGCThreadStaticsBasePointer(TypeHandle typeHandle, Tar return threadContract.GetThreadLocalStaticBase(threadPtr, tlsIndexPtr); } - public TargetPointer GetGCStaticsBasePointer(TypeHandle typeHandle) + public TargetPointer GetGCStaticsBasePointer(ITypeHandle typeHandle) { TargetPointer dynamicStaticsInfoAddr = GetDynamicStaticsInfo(typeHandle); if (dynamicStaticsInfoAddr == TargetPointer.Null) @@ -977,7 +977,7 @@ public TargetPointer GetGCStaticsBasePointer(TypeHandle typeHandle) return dynamicStaticsInfo.GCStatics; } - public TargetPointer GetNonGCStaticsBasePointer(TypeHandle typeHandle) + public TargetPointer GetNonGCStaticsBasePointer(ITypeHandle typeHandle) { TargetPointer dynamicStaticsInfoAddr = GetDynamicStaticsInfo(typeHandle); if (dynamicStaticsInfoAddr == TargetPointer.Null) @@ -986,7 +986,7 @@ public TargetPointer GetNonGCStaticsBasePointer(TypeHandle typeHandle) return dynamicStaticsInfo.NonGCStatics; } - public ReadOnlySpan GetInstantiation(TypeHandle typeHandle) + public ReadOnlySpan GetInstantiation(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return default; @@ -998,7 +998,7 @@ public ReadOnlySpan GetInstantiation(TypeHandle typeHandle) return _target.ProcessedData.GetOrAdd(typeHandle.Address).TypeHandles; } - public bool IsClassInited(TypeHandle typeHandle) + public bool IsClassInited(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -1007,7 +1007,7 @@ public bool IsClassInited(TypeHandle typeHandle) return (auxiliaryData.Flags & (uint)MethodTableAuxiliaryFlags.Initialized) != 0; } - public bool IsInitError(TypeHandle typeHandle) + public bool IsInitError(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -1020,7 +1020,7 @@ private sealed class TypeInstantiation : IData { public static TypeInstantiation Create(Target target, TargetPointer address) => new TypeInstantiation(target, address); - public TypeHandle[] TypeHandles { get; } + public ITypeHandle[] TypeHandles { get; } private TypeInstantiation(Target target, TargetPointer typePointer) { RuntimeTypeSystem_1 rts = (RuntimeTypeSystem_1)target.Contracts.RuntimeTypeSystem; @@ -1036,7 +1036,7 @@ private TypeInstantiation(Target target, TargetPointer typePointer) TargetPointer dictionaryPointer = target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)(genericsDictInfo.NumDicts - 1)); int numberOfGenericArgs = genericsDictInfo.NumTypeArgs; - TypeHandles = new TypeHandle[numberOfGenericArgs]; + TypeHandles = new ITypeHandle[numberOfGenericArgs]; for (int i = 0; i < numberOfGenericArgs; i++) { TypeHandles[i] = rts.GetTypeHandle(target.ReadPointer(dictionaryPointer + (ulong)target.PointerSize * (ulong)i)); @@ -1044,8 +1044,8 @@ private TypeInstantiation(Target target, TargetPointer typePointer) } } - public bool IsGenericTypeDefinition(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsGenericTypeDefinition; - public bool ContainsGenericVariables(TypeHandle typeHandle) + public bool IsGenericTypeDefinition(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsGenericTypeDefinition; + public bool ContainsGenericVariables(ITypeHandle typeHandle) { if (typeHandle.IsTypeDesc()) { @@ -1060,8 +1060,8 @@ public bool ContainsGenericVariables(TypeHandle typeHandle) else if (type == CorElementType.FnPtr) { - _ = IsFunctionPointer(typeHandle, out ReadOnlySpan signatureTypeArgs, out _); - foreach (TypeHandle sigTypeArg in signatureTypeArgs) + _ = IsFunctionPointer(typeHandle, out ReadOnlySpan signatureTypeArgs, out _); + foreach (ITypeHandle sigTypeArg in signatureTypeArgs) { if (ContainsGenericVariables(sigTypeArg)) return true; @@ -1073,8 +1073,8 @@ public bool ContainsGenericVariables(TypeHandle typeHandle) return _methodTables[typeHandle.Address].Flags.ContainsGenericVariables; } - public bool IsCollectible(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsCollectible; - public bool HasTypeParam(TypeHandle typeHandle) + public bool IsCollectible(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsCollectible; + public bool HasTypeParam(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1096,7 +1096,7 @@ public bool HasTypeParam(TypeHandle typeHandle) return false; } - public CorElementType GetSignatureCorElementType(TypeHandle typeHandle) + public CorElementType GetSignatureCorElementType(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1127,7 +1127,7 @@ public CorElementType GetSignatureCorElementType(TypeHandle typeHandle) return default; } - public CorElementType GetInternalCorElementType(TypeHandle typeHandle) + public CorElementType GetInternalCorElementType(ITypeHandle typeHandle) { CorElementType sigType = GetSignatureCorElementType(typeHandle); if (sigType == CorElementType.ValueType && typeHandle.IsMethodTable()) @@ -1140,7 +1140,7 @@ public CorElementType GetInternalCorElementType(TypeHandle typeHandle) return sigType; } - public bool IsValueType(TypeHandle typeHandle) + public bool IsValueType(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1156,7 +1156,7 @@ public bool IsValueType(TypeHandle typeHandle) return false; } - public bool IsEnum(TypeHandle typeHandle) + public bool IsEnum(ITypeHandle typeHandle) { // Enums have Category_Primitive in their MethodTable flags and their // InternalCorElementType is a primitive type (I1, U1, I2, U2, I4, U4, I8, U8), @@ -1168,7 +1168,7 @@ public bool IsEnum(TypeHandle typeHandle) return methodTable.Flags.GetFlag(MethodTableFlags_1.WFLAGS_HIGH.Category_Mask) == MethodTableFlags_1.WFLAGS_HIGH.Category_Primitive; } - public bool IsDelegate(TypeHandle typeHandle) + public bool IsDelegate(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -1177,8 +1177,8 @@ public bool IsDelegate(TypeHandle typeHandle) return parentMT == _multicastDelegateMethodTablePointer; } - // return true if the TypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. - public bool IsArray(TypeHandle typeHandle, out uint rank) + // return true if the ITypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. + public bool IsArray(ITypeHandle typeHandle, out uint rank) { if (typeHandle.IsMethodTable()) { @@ -1203,7 +1203,7 @@ public bool IsArray(TypeHandle typeHandle, out uint rank) return false; } - public TypeHandle GetTypeParam(TypeHandle typeHandle) + public ITypeHandle GetTypeParam(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1229,9 +1229,9 @@ public TypeHandle GetTypeParam(TypeHandle typeHandle) throw new ArgumentException(nameof(typeHandle)); } - private TypeHandle GetRootTypeParam(TypeHandle typeHandle) + private ITypeHandle GetRootTypeParam(ITypeHandle typeHandle) { - TypeHandle current = typeHandle; + ITypeHandle current = typeHandle; while (HasTypeParam(current)) { current = GetTypeParam(current); @@ -1239,9 +1239,9 @@ private TypeHandle GetRootTypeParam(TypeHandle typeHandle) return current; } - private bool GenericInstantiationMatch(TypeHandle genericType, TypeHandle potentialMatch, ImmutableArray typeArguments) + private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle potentialMatch, ImmutableArray typeArguments) { - ReadOnlySpan instantiation = GetInstantiation(potentialMatch); + ReadOnlySpan instantiation = GetInstantiation(potentialMatch); if (instantiation.Length != typeArguments.Length) return false; @@ -1259,7 +1259,7 @@ private bool GenericInstantiationMatch(TypeHandle genericType, TypeHandle potent return true; } - private bool ArrayPtrMatch(TypeHandle elementType, CorElementType corElementType, int rank, TypeHandle potentialMatch) + private bool ArrayPtrMatch(ITypeHandle elementType, CorElementType corElementType, int rank, ITypeHandle potentialMatch) { IsArray(potentialMatch, out uint typeHandleRank); return GetSignatureCorElementType(potentialMatch) == corElementType && @@ -1269,9 +1269,9 @@ private bool ArrayPtrMatch(TypeHandle elementType, CorElementType corElementType } - private bool FnPtrMatch(TypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) + private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) { - if (!IsFunctionPointer(candidate, out ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) + if (!IsFunctionPointer(candidate, out ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) return false; if (candidateCallConv != callConv) return false; @@ -1285,7 +1285,7 @@ private bool FnPtrMatch(TypeHandle candidate, ImmutableArray retAndA return true; } - private bool IsLoaded(TypeHandle typeHandle) + private bool IsLoaded(ITypeHandle typeHandle) { if (typeHandle.Address == TargetPointer.Null) return false; @@ -1300,11 +1300,11 @@ private bool IsLoaded(TypeHandle typeHandle) return (auxData.Flags & (uint)MethodTableAuxiliaryFlags.IsNotFullyLoaded) == 0; // IsUnloaded } - TypeHandle IRuntimeTypeSystem.GetConstructedType(TypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) + ITypeHandle IRuntimeTypeSystem.GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) { if (typeHandle.Address == TargetPointer.Null && corElementType != CorElementType.FnPtr) - return new TypeHandle(TargetPointer.Null); - if (_typeHandles.TryGetValue(new TypeKey(typeHandle, corElementType, rank, typeArguments, callConv), out TypeHandle existing)) + return new ITypeHandle(TargetPointer.Null); + if (_typeHandles.TryGetValue(new TypeKey(typeHandle, corElementType, rank, typeArguments, callConv), out ITypeHandle existing)) return existing; ILoader loaderContract = _target.Contracts.Loader; TargetPointer loaderModule; @@ -1316,7 +1316,7 @@ TypeHandle IRuntimeTypeSystem.GetConstructedType(TypeHandle typeHandle, CorEleme loaderModule = GetLoaderModule(typeHandle); ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(loaderModule); - TypeHandle potentialMatch; + ITypeHandle potentialMatch; foreach (TargetPointer ptr in loaderContract.GetAvailableTypeParams(moduleHandle)) { potentialMatch = GetTypeHandle(ptr); @@ -1342,11 +1342,11 @@ TypeHandle IRuntimeTypeSystem.GetConstructedType(TypeHandle typeHandle, CorEleme return potentialMatch; } } - return new TypeHandle(TargetPointer.Null); + return new ITypeHandle(TargetPointer.Null); } // See https://github.com/dotnet/runtime/blob/e1979b72ccb5f916649f1d9949ef663254790c25/src/coreclr/vm/clsload.cpp#L78 - private TargetPointer ComputeLoaderModule(TargetPointer definitionModule, ImmutableArray inst) + private TargetPointer ComputeLoaderModule(TargetPointer definitionModule, ImmutableArray inst) { ILoader loaderContract = _target.Contracts.Loader; TargetPointer latestLoaderModule = TargetPointer.Null; @@ -1361,7 +1361,7 @@ private TargetPointer ComputeLoaderModule(TargetPointer definitionModule, Immuta } bool anyCollectible = false; - foreach (TypeHandle arg in inst) + foreach (ITypeHandle arg in inst) { if (arg.Address == TargetPointer.Null) continue; @@ -1416,7 +1416,7 @@ private bool TryGetCollectibleLoaderAllocator(TargetPointer modulePtr, [NotNullW return true; } - TypeHandle IRuntimeTypeSystem.GetPrimitiveType(CorElementType typeCode) + ITypeHandle IRuntimeTypeSystem.GetPrimitiveType(CorElementType typeCode) { TargetPointer coreLib = _target.ReadGlobalPointer(Constants.Globals.CoreLib); CoreLibBinder coreLibData = _target.ProcessedData.GetOrAdd(coreLib); @@ -1424,7 +1424,7 @@ TypeHandle IRuntimeTypeSystem.GetPrimitiveType(CorElementType typeCode) return GetTypeHandle(typeHandlePtr); } - public bool IsGenericVariable(TypeHandle typeHandle, out TargetPointer module, out uint token) + public bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token) { module = TargetPointer.Null; token = 0; @@ -1446,7 +1446,7 @@ public bool IsGenericVariable(TypeHandle typeHandle, out TargetPointer module, o return false; } - public bool IsFunctionPointer(TypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) + public bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) { retAndArgTypes = default; callConv = default; @@ -1465,7 +1465,7 @@ public bool IsFunctionPointer(TypeHandle typeHandle, out ReadOnlySpan typeHandle.IsTypeDesc(); + public bool IsTypeDesc(ITypeHandle typeHandle) => typeHandle.IsTypeDesc(); public TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) { @@ -1483,7 +1483,7 @@ public TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) return new TypedByRefInfo(typedByRefData.Data, typedByRefData.Type); } - public TargetPointer GetLoaderModule(TypeHandle typeHandle) + public TargetPointer GetLoaderModule(ITypeHandle typeHandle) { if (typeHandle.IsTypeDesc()) { @@ -1513,7 +1513,7 @@ private sealed class FunctionPointerRetAndArgs : IData new FunctionPointerRetAndArgs(target, address); - public TypeHandle[] TypeHandles { get; } + public ITypeHandle[] TypeHandles { get; } private FunctionPointerRetAndArgs(Target target, TargetPointer typePointer) { RuntimeTypeSystem_1 rts = (RuntimeTypeSystem_1)target.Contracts.RuntimeTypeSystem; @@ -1522,7 +1522,7 @@ private FunctionPointerRetAndArgs(Target target, TargetPointer typePointer) TargetPointer retAndArgs = fnPtrTypeDesc.RetAndArgTypes; int numberOfRetAndArgTypes = checked((int)fnPtrTypeDesc.NumArgs + 1); - TypeHandles = new TypeHandle[numberOfRetAndArgTypes]; + TypeHandles = new ITypeHandle[numberOfRetAndArgTypes]; for (int i = 0; i < numberOfRetAndArgTypes; i++) { TypeHandles[i] = rts.GetTypeHandle(target.ReadPointer(retAndArgs + (ulong)target.PointerSize * (ulong)i)); @@ -1594,7 +1594,7 @@ public bool IsGenericMethodDefinition(MethodDescHandle methodDescHandle) return AsInstantiatedMethodDesc(methodDesc).IsGenericMethodDefinition; } - public ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) + public ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) { MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; @@ -1877,7 +1877,7 @@ private VtableIndirections GetVTableIndirections(TargetPointer methodTableAddres return new VtableIndirections(_target, methodTableAddress + typeInfo.Size!.Value); } - private TargetPointer GetAddressOfSlot(TypeHandle typeHandle, uint slotNum) + private TargetPointer GetAddressOfSlot(ITypeHandle typeHandle, uint slotNum) { if (!typeHandle.IsMethodTable()) throw new InvalidOperationException($"nameof{typeHandle} is not a MethodTable"); @@ -1938,7 +1938,7 @@ private TargetPointer GetLoaderModule(MethodDesc md) else { TargetPointer mtAddr = GetMethodTable(new MethodDescHandle(md.Address)); - TypeHandle mt = GetTypeHandle(mtAddr); + ITypeHandle mt = GetTypeHandle(mtAddr); return GetLoaderModule(mt); } } @@ -1997,7 +1997,7 @@ bool IRuntimeTypeSystem.HasNativeCodeSlot(MethodDescHandle methodDesc) } // Based on MethodTable::IntroducedMethodIterator - private IEnumerable GetIntroducedMethods(TypeHandle typeHandle) + private IEnumerable GetIntroducedMethods(ITypeHandle typeHandle) { Debug.Assert(typeHandle.IsMethodTable()); @@ -2023,12 +2023,12 @@ private IEnumerable GetIntroducedMethods(TypeHandle typeHandle } } - IEnumerable IRuntimeTypeSystem.GetIntroducedMethodDescs(TypeHandle typeHandle) + IEnumerable IRuntimeTypeSystem.GetIntroducedMethodDescs(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) yield break; - TypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); + ITypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); foreach (MethodDescHandle mdh in GetIntroducedMethods(canonMT)) { yield return mdh.Address; @@ -2037,13 +2037,13 @@ IEnumerable IRuntimeTypeSystem.GetIntroducedMethodDescs(TypeHandl // Uses GetMethodDescForVtableSlot if slot is less than the number of vtable slots // otherwise looks for the slot in the introduced methods - TargetPointer IRuntimeTypeSystem.GetMethodDescForSlot(TypeHandle typeHandle, ushort slot) + TargetPointer IRuntimeTypeSystem.GetMethodDescForSlot(ITypeHandle typeHandle, ushort slot) { if (!typeHandle.IsMethodTable()) // TypeDesc do not contain any slots. return TargetPointer.Null; - TypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); + ITypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); if (slot < GetNumVtableSlots(canonMT)) { return GetMethodDescForVtableSlot(canonMT, slot); @@ -2062,7 +2062,7 @@ TargetPointer IRuntimeTypeSystem.GetMethodDescForSlot(TypeHandle typeHandle, ush } } - private TargetPointer GetMethodDescForVtableSlot(TypeHandle typeHandle, ushort slot) + private TargetPointer GetMethodDescForVtableSlot(ITypeHandle typeHandle, ushort slot) { // based on MethodTable::GetMethodDescForSlot_NoThrow if (!typeHandle.IsMethodTable()) @@ -2070,7 +2070,7 @@ private TargetPointer GetMethodDescForVtableSlot(TypeHandle typeHandle, ushort s throw new ArgumentException(nameof(slot), "Slot number is greater than the number of slots"); TargetPointer cannonMTPTr = GetCanonicalMethodTable(typeHandle); - TypeHandle canonMT = GetTypeHandle(cannonMTPTr); + ITypeHandle canonMT = GetTypeHandle(cannonMTPTr); if (slot >= GetNumVtableSlots(canonMT)) throw new ArgumentException(nameof(slot), "Slot number is greater than the number of slots"); @@ -2083,7 +2083,7 @@ private TargetPointer GetMethodDescForVtableSlot(TypeHandle typeHandle, ushort s while (lookupMTPtr != TargetPointer.Null) { // if pCode is null, we iterate through the method descs in the MT. - TypeHandle lookupMT = GetTypeHandle(lookupMTPtr); + ITypeHandle lookupMT = GetTypeHandle(lookupMTPtr); foreach (MethodDescHandle mdh in GetIntroducedMethods(lookupMT)) { MethodDesc md = _methodDescs[mdh.Address]; @@ -2119,7 +2119,7 @@ private readonly TargetPointer GetMethodDescForEntrypoint(TargetCodePointer pCod } } - TargetCodePointer IRuntimeTypeSystem.GetSlot(TypeHandle typeHandle, uint slot) + TargetCodePointer IRuntimeTypeSystem.GetSlot(ITypeHandle typeHandle, uint slot) { // based on MethodTable::GetSlot(uint slotNumber) @@ -2181,7 +2181,7 @@ private TargetCodePointer GetMethodEntryPointIfExists(MethodDesc md) } TargetPointer methodTablePointer = md.MethodTable; - TypeHandle typeHandle = GetTypeHandle(methodTablePointer); + ITypeHandle typeHandle = GetTypeHandle(methodTablePointer); Debug.Assert(_methodTables[typeHandle.Address].IsCanonMT); TargetPointer addrOfSlot = GetAddressOfSlot(typeHandle, md.Slot); return _target.ReadCodePointer(addrOfSlot); @@ -2275,7 +2275,7 @@ public TargetPointer GetAddressOfMethodTableSlot(TargetPointer methodTablePointe // for the benefit of MethodValidation private TargetPointer GetAddressOfMethodTableSlot(TargetPointer methodTablePointer, uint slot) { - TypeHandle typeHandle = GetTypeHandle(methodTablePointer); + ITypeHandle typeHandle = GetTypeHandle(methodTablePointer); Debug.Assert(_methodTables[typeHandle.Address].IsCanonMT); TargetPointer addrOfSlot = GetAddressOfSlot(typeHandle, slot); return addrOfSlot; @@ -2283,7 +2283,7 @@ private TargetPointer GetAddressOfMethodTableSlot(TargetPointer methodTablePoint private bool SlotIsVtableSlot(TargetPointer methodTablePointer, uint slot) { - TypeHandle typeHandle = GetTypeHandle(methodTablePointer); + ITypeHandle typeHandle = GetTypeHandle(methodTablePointer); return slot < GetNumVtableSlots(typeHandle); } TargetPointer IRuntimeTypeSystem.GetMTOfEnclosingClass(TargetPointer fieldDescPointer) @@ -2339,14 +2339,14 @@ uint IRuntimeTypeSystem.GetFieldDescOffset(TargetPointer fieldDescPointer, Field return offset; } - TypeHandle IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) + ITypeHandle IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) { try { TargetPointer enclosingMT = ((IRuntimeTypeSystem)this).GetMTOfEnclosingClass(fieldDescPointer); if (enclosingMT == TargetPointer.Null) return default; - TypeHandle enclosingType = GetTypeHandle(enclosingMT); + ITypeHandle enclosingType = GetTypeHandle(enclosingMT); TargetPointer modulePtr = GetModule(enclosingType); if (modulePtr == TargetPointer.Null) return default; @@ -2386,7 +2386,7 @@ bool IRuntimeTypeSystem.TryGetFieldDescNext(TargetPointer fieldDescPointer, out return true; } - TargetPointer IRuntimeTypeSystem.GetFieldDescByName(TypeHandle typeHandle, string fieldName) + TargetPointer IRuntimeTypeSystem.GetFieldDescByName(ITypeHandle typeHandle, string fieldName) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -2444,7 +2444,7 @@ private TargetPointer GetStaticAddressHandle(TargetPointer @base, uint offset, b private TargetPointer GetFieldDescStaticOrThreadStaticAddress(TargetPointer fieldDescPointer, TargetPointer? thread = null, bool unboxValueTypes = true) { TargetPointer enclosingMT = ((IRuntimeTypeSystem)this).GetMTOfEnclosingClass(fieldDescPointer); - TypeHandle ctx = GetTypeHandle(enclosingMT); + ITypeHandle ctx = GetTypeHandle(enclosingMT); TargetPointer modulePtr = GetModule(ctx); ILoader loader = _target.Contracts.Loader; ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs index a8d9b15251dd40..722247e1f4fe1e 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs @@ -21,13 +21,13 @@ public interface IRuntimeSignatureTypeProvider { /// /// Classify an ELEMENT_TYPE_INTERNAL (0x21) type by resolving the - /// embedded TypeHandle pointer via the target's runtime type system. + /// embedded ITypeHandle pointer via the target's runtime type system. /// TType GetInternalType(TargetPointer typeHandlePointer); /// /// Classify an ELEMENT_TYPE_CMOD_INTERNAL (0x22) custom modifier by - /// resolving the embedded TypeHandle pointer via the target's runtime type system. + /// resolving the embedded ITypeHandle pointer via the target's runtime type system. /// TType GetInternalModifiedType(TargetPointer typeHandlePointer, TType unmodifiedType, bool isRequired); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs index c6cb2bfb47fbd5..10cbdd6b498cb2 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs @@ -10,7 +10,7 @@ namespace Microsoft.Diagnostics.DataContractReader.SignatureHelpers; -public class SignatureTypeProvider : IRuntimeSignatureTypeProvider +public class SignatureTypeProvider : IRuntimeSignatureTypeProvider { private readonly Target _target; private readonly Contracts.ModuleHandle _moduleHandle; @@ -25,19 +25,19 @@ public SignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHandle) _runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; } - public TypeHandle GetArrayType(TypeHandle elementType, ArrayShape shape) + public ITypeHandle GetArrayType(ITypeHandle elementType, ArrayShape shape) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.Array, shape.Rank, []); - public TypeHandle GetByReferenceType(TypeHandle elementType) + public ITypeHandle GetByReferenceType(ITypeHandle elementType) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.Byref, 0, []); - public TypeHandle GetFunctionPointerType(MethodSignature signature) + public ITypeHandle GetFunctionPointerType(MethodSignature signature) => GetPrimitiveType(PrimitiveTypeCode.IntPtr); - public TypeHandle GetGenericInstantiation(TypeHandle genericType, ImmutableArray typeArguments) + public ITypeHandle GetGenericInstantiation(ITypeHandle genericType, ImmutableArray typeArguments) => _runtimeTypeSystem.GetConstructedType(genericType, CorElementType.GenericInst, 0, typeArguments); - public TypeHandle GetGenericMethodParameter(T context, int index) + public ITypeHandle GetGenericMethodParameter(T context, int index) { if (typeof(T) == typeof(MethodDescHandle)) { @@ -46,55 +46,55 @@ public TypeHandle GetGenericMethodParameter(T context, int index) } throw new NotSupportedException(); } - public TypeHandle GetGenericTypeParameter(T context, int index) + public ITypeHandle GetGenericTypeParameter(T context, int index) { - TypeHandle typeContext; - if (typeof(T) == typeof(TypeHandle)) + ITypeHandle typeContext; + if (typeof(T) == typeof(ITypeHandle)) { - typeContext = (TypeHandle)(object)context!; + typeContext = (ITypeHandle)(object)context!; return _runtimeTypeSystem.GetInstantiation(typeContext)[index]; } throw new NotImplementedException(); } - public TypeHandle GetModifiedType(TypeHandle modifier, TypeHandle unmodifiedType, bool isRequired) + public ITypeHandle GetModifiedType(ITypeHandle modifier, ITypeHandle unmodifiedType, bool isRequired) => unmodifiedType; - public TypeHandle GetPinnedType(TypeHandle elementType) + public ITypeHandle GetPinnedType(ITypeHandle elementType) => elementType; - public TypeHandle GetPointerType(TypeHandle elementType) + public ITypeHandle GetPointerType(ITypeHandle elementType) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.Ptr, 0, []); - public TypeHandle GetPrimitiveType(PrimitiveTypeCode typeCode) + public ITypeHandle GetPrimitiveType(PrimitiveTypeCode typeCode) => _runtimeTypeSystem.GetPrimitiveType((CorElementType)typeCode); - public TypeHandle GetSZArrayType(TypeHandle elementType) + public ITypeHandle GetSZArrayType(ITypeHandle elementType) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.SzArray, 1, []); - public TypeHandle GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) + public ITypeHandle GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) { int token = MetadataTokens.GetToken((EntityHandle)handle); TargetPointer typeDefToMethodTable = _loader.GetLookupTables(_moduleHandle).TypeDefToMethodTable; TargetPointer typeHandlePtr = _loader.GetModuleLookupMapElement(typeDefToMethodTable, (uint)token, out _); - return typeHandlePtr == TargetPointer.Null ? new TypeHandle(TargetPointer.Null) : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); + return typeHandlePtr == TargetPointer.Null ? new ITypeHandle(TargetPointer.Null) : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); } - public TypeHandle GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) + public ITypeHandle GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) { int token = MetadataTokens.GetToken((EntityHandle)handle); TargetPointer typeRefToMethodTable = _loader.GetLookupTables(_moduleHandle).TypeRefToMethodTable; TargetPointer typeHandlePtr = _loader.GetModuleLookupMapElement(typeRefToMethodTable, (uint)token, out _); - return typeHandlePtr == TargetPointer.Null ? new TypeHandle(TargetPointer.Null) : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); + return typeHandlePtr == TargetPointer.Null ? new ITypeHandle(TargetPointer.Null) : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); } - public TypeHandle GetTypeFromSpecification(MetadataReader reader, T context, TypeSpecificationHandle handle, byte rawTypeKind) + public ITypeHandle GetTypeFromSpecification(MetadataReader reader, T context, TypeSpecificationHandle handle, byte rawTypeKind) => throw new NotImplementedException(); - public TypeHandle GetInternalType(TargetPointer typeHandlePointer) + public ITypeHandle GetInternalType(TargetPointer typeHandlePointer) => typeHandlePointer == TargetPointer.Null - ? new TypeHandle(TargetPointer.Null) + ? new ITypeHandle(TargetPointer.Null) : _runtimeTypeSystem.GetTypeHandle(typeHandlePointer); - public TypeHandle GetInternalModifiedType(TargetPointer typeHandlePointer, TypeHandle unmodifiedType, bool isRequired) + public ITypeHandle GetInternalModifiedType(TargetPointer typeHandlePointer, ITypeHandle unmodifiedType, bool isRequired) => unmodifiedType; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs index e3c2531d8d4be6..b3412452ec63d7 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs @@ -18,7 +18,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal sealed class Signature_1 : ISignature { private readonly Target _target; - private readonly Dictionary> _thProviders = []; + private readonly Dictionary> _thProviders = []; internal Signature_1(Target target) { @@ -30,25 +30,25 @@ public void Flush(FlushScope scope) _thProviders.Clear(); } - private SignatureTypeProvider GetTypeHandleProvider(ModuleHandle moduleHandle) + private SignatureTypeProvider GetTypeHandleProvider(ModuleHandle moduleHandle) { - if (_thProviders.TryGetValue(moduleHandle, out SignatureTypeProvider? thProvider)) + if (_thProviders.TryGetValue(moduleHandle, out SignatureTypeProvider? thProvider)) { return thProvider; } - SignatureTypeProvider newProvider = new(_target, moduleHandle); + SignatureTypeProvider newProvider = new(_target, moduleHandle); _thProviders[moduleHandle] = newProvider; return newProvider; } - TypeHandle ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, TypeHandle ctx) + ITypeHandle ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) { - SignatureTypeProvider provider = GetTypeHandleProvider(moduleHandle); + SignatureTypeProvider provider = GetTypeHandleProvider(moduleHandle); MetadataReader mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle)!; BlobReader blobReader = mdReader.GetBlobReader(blobHandle); - RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); + RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); return decoder.DecodeFieldSignature(ref blobReader); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameHelpers.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameHelpers.cs index afed34ea85f511..2ad10304b65424 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameHelpers.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameHelpers.cs @@ -116,7 +116,7 @@ public TargetPointer GetMethodDescPtr(TargetPointer framePtr) else if (stubDispatchFrame.RepresentativeMTPtr != TargetPointer.Null) { IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; - TypeHandle mtHandle = rtsContract.GetTypeHandle(stubDispatchFrame.RepresentativeMTPtr); + ITypeHandle mtHandle = rtsContract.GetTypeHandle(stubDispatchFrame.RepresentativeMTPtr); return rtsContract.GetMethodDescForSlot(mtHandle, (ushort)stubDispatchFrame.RepresentativeSlot); } else diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs index 8852f733df6a97..3c380e16f1ac6d 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs @@ -28,10 +28,10 @@ internal enum GcTypeKind /// /// Generic context used to resolve ELEMENT_TYPE_VAR and ELEMENT_TYPE_MVAR /// while decoding a method signature for GC scanning. is the -/// owning type's (used for VAR), and +/// owning type's (used for VAR), and /// is the owning method's (used for MVAR). /// -internal readonly record struct GcSignatureContext(TypeHandle ClassContext, MethodDescHandle MethodContext); +internal readonly record struct GcSignatureContext(ITypeHandle ClassContext, MethodDescHandle MethodContext); /// /// Classifies signature types for GC scanning purposes. @@ -87,7 +87,7 @@ public GcTypeKind GetGenericMethodParameter(GcSignatureContext genericContext, i { try { - ReadOnlySpan instantiation = _target.Contracts.RuntimeTypeSystem.GetGenericMethodInstantiation(genericContext.MethodContext); + ReadOnlySpan instantiation = _target.Contracts.RuntimeTypeSystem.GetGenericMethodInstantiation(genericContext.MethodContext); if ((uint)index >= (uint)instantiation.Length) return GcTypeKind.Ref; return ClassifyTypeHandle(instantiation[index]); @@ -103,7 +103,7 @@ public GcTypeKind GetGenericTypeParameter(GcSignatureContext genericContext, int try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle classCtx = genericContext.ClassContext; + ITypeHandle classCtx = genericContext.ClassContext; if (rts.IsArray(classCtx, out _)) { @@ -117,7 +117,7 @@ public GcTypeKind GetGenericTypeParameter(GcSignatureContext genericContext, int return ClassifyTypeHandle(rts.GetTypeParam(classCtx)); } - ReadOnlySpan instantiation = rts.GetInstantiation(classCtx); + ReadOnlySpan instantiation = rts.GetInstantiation(classCtx); if ((uint)index >= (uint)instantiation.Length) return GcTypeKind.Ref; return ClassifyTypeHandle(instantiation[index]); @@ -150,7 +150,7 @@ public GcTypeKind GetInternalType(TargetPointer typeHandlePointer) /// /// Resolve a TypeDef/TypeRef token via the module's lookup tables and classify the - /// resulting . Falls back to a -based + /// resulting . Falls back to a -based /// classification when the type has not been loaded. /// private GcTypeKind ClassifyTokenLookup(TargetPointer lookupTable, int token, byte rawTypeKind) @@ -170,12 +170,12 @@ private GcTypeKind ClassifyTokenLookup(TargetPointer lookupTable, int token, byt } /// - /// Classify a resolved . Mirrors native + /// Classify a resolved . Mirrors native /// SigPointer::PeekElemTypeNormalized + gElementTypeInfo[etype].m_gc: /// enums collapse to their underlying primitive () so /// they are skipped during stack scanning, matching native behavior. /// - private GcTypeKind ClassifyTypeHandle(TypeHandle typeHandle) + private GcTypeKind ClassifyTypeHandle(ITypeHandle typeHandle) { if (typeHandle.Address == TargetPointer.Null) return GcTypeKind.Ref; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs index 2dd9a6dde7e947..2ceafa34213cd6 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs @@ -7,17 +7,17 @@ namespace Microsoft.Diagnostics.DataContractReader.RuntimeTypeSystemHelpers; internal static class ExtensionMethods { - public static bool IsTypeDesc(this TypeHandle type) + public static bool IsTypeDesc(this ITypeHandle type) { return type.Address != 0 && ((ulong)type.Address & (ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask) == (ulong)RuntimeTypeSystem_1.TypeHandleBits.TypeDesc; } - public static bool IsMethodTable(this TypeHandle type) + public static bool IsMethodTable(this ITypeHandle type) { return type.Address != 0 && ((ulong)type.Address & (ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask) == (ulong)RuntimeTypeSystem_1.TypeHandleBits.MethodTable; } - public static TargetPointer TypeDescAddress(this TypeHandle type) + public static TargetPointer TypeDescAddress(this ITypeHandle type) { if (!type.IsTypeDesc()) return 0; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs index bba01ef999fe51..d4d5db77e48e52 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs @@ -429,7 +429,7 @@ private MethodDescHandle GetFrameMethodDesc(out Contracts.ModuleHandle moduleHan MethodDescHandle mdh = rts.GetMethodDescHandle(methodDescPtr); TargetPointer mtAddr = rts.GetMethodTable(mdh); - TypeHandle typeHandle = rts.GetTypeHandle(mtAddr); + ITypeHandle typeHandle = rts.GetTypeHandle(mtAddr); TargetPointer modulePtr = rts.GetModule(typeHandle); moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); @@ -742,7 +742,7 @@ public FlagSignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHan try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(mdh); + ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(mdh); return ResolveGenericParam(rts, methodInst[index]); } catch (System.Exception) { return ((uint)ClrDataValueFlag.DEFAULT, -1); } @@ -754,14 +754,14 @@ public FlagSignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHan { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = rts.GetMethodTable(mdh); - TypeHandle declaringType = rts.GetTypeHandle(mtAddr); - ReadOnlySpan typeInst = rts.GetInstantiation(declaringType); + ITypeHandle declaringType = rts.GetTypeHandle(mtAddr); + ReadOnlySpan typeInst = rts.GetInstantiation(declaringType); return ResolveGenericParam(rts, typeInst[index]); } catch (System.Exception) { return ((uint)ClrDataValueFlag.DEFAULT, -1); } } - private static (uint Flags, int Size) ResolveGenericParam(IRuntimeTypeSystem rts, TypeHandle resolvedType) + private static (uint Flags, int Size) ResolveGenericParam(IRuntimeTypeSystem rts, ITypeHandle resolvedType) { CorElementType elementType = rts.GetSignatureCorElementType(resolvedType); (uint flags, int size) = MapCorElementTypeToFlags(elementType); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs index e74f15f6937658..bf5ec73d4eff2b 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs @@ -45,7 +45,7 @@ private static bool HasClassInstantiation(Target target, MethodDescHandle md) { IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = rts.GetMethodTable(md); - TypeHandle mt = rts.GetTypeHandle(mtAddr); + ITypeHandle mt = rts.GetTypeHandle(mtAddr); return !rts.GetInstantiation(mt).IsEmpty; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs index db2c52765a6b5a..b314489ea31756 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs @@ -63,7 +63,7 @@ int IXCLRDataMethodInstance.GetTokenAndScope(uint* token, DacComNullableByRef fpCallback, nint pUserData, List? cdacFields) @@ -2626,7 +2626,7 @@ private static void EmitFieldData( TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fdPtr); if (enclosingMT != TargetPointer.Null) { - TypeHandle enclosingTh = rts.GetTypeHandle(enclosingMT); + ITypeHandle enclosingTh = rts.GetTypeHandle(enclosingMT); isCollectibleStatic = rts.IsCollectible(enclosingTh); } } @@ -2726,7 +2726,7 @@ public int TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, ulong vmTypeHa try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle th = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); + ITypeHandle th = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); TypeHandleToExpandedTypeInfoImpl(rts, boxed, th, pTypeInfo); } catch (System.Exception ex) @@ -2755,7 +2755,7 @@ public int GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, ulong addr, Debug { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = _target.Contracts.Object.GetMethodTableAddress(new TargetPointer(addr)); - TypeHandle th = rts.GetTypeHandle(mtAddr); + ITypeHandle th = rts.GetTypeHandle(mtAddr); TypeHandleToExpandedTypeInfoImpl(rts, boxed, th, pTypeInfo); } catch (System.Exception ex) @@ -2879,10 +2879,10 @@ public int GetApproxTypeHandle(TypeInfoList* pTypeData, ulong* pRetVal) TargetPointer canonMtPtr = rts.GetWellKnownMethodTable(WellKnownMethodTable.Canon); if (canonMtPtr == TargetPointer.Null) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; - TypeHandle canonTh = rts.GetTypeHandle(canonMtPtr); + ITypeHandle canonTh = rts.GetTypeHandle(canonMtPtr); TypeDataWalk walk = new TypeDataWalk(_target, rts, canonTh, pTypeData->m_pList, (uint)pTypeData->m_nEntries); - TypeHandle th = walk.ReadLoadedTypeHandle(); + ITypeHandle th = walk.ReadLoadedTypeHandle(); if (th.IsNull) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; *pRetVal = th.Address.Value; @@ -2914,7 +2914,7 @@ public int GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData* pTypeData, ArgInfoL try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle th = default; + ITypeHandle th = default; CorElementType et = (CorElementType)ReadLittleEndian(pTypeData->elementType); switch (et) { @@ -2958,10 +2958,10 @@ public int GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData* pTypeData, ArgInfoL return hr; } - private TypeHandle BasicTypeInfoToTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_BasicTypeData* pData) + private ITypeHandle BasicTypeInfoToTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_BasicTypeData* pData) { CorElementType et = (CorElementType)ReadLittleEndian(pData->elementType); - TypeHandle th; + ITypeHandle th; switch (et) { case CorElementType.Array: @@ -2987,7 +2987,7 @@ private TypeHandle BasicTypeInfoToTypeHandle(IRuntimeTypeSystem rts, DebuggerIPC return th; } - private TypeHandle GetClassOrValueTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_BasicTypeData* pData) + private ITypeHandle GetClassOrValueTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_BasicTypeData* pData) { ulong vmTh = ReadLittleEndian(pData->vmTypeHandle); if (vmTh != 0) @@ -2998,46 +2998,46 @@ private TypeHandle GetClassOrValueTypeHandle(IRuntimeTypeSystem rts, DebuggerIPC return LookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); } - private TypeHandle GetExactArrayTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) + private ITypeHandle GetExactArrayTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) { if (pArgInfo->m_nEntries != 1) throw new ArgumentException($"Array type with arg count: {pArgInfo->m_nEntries}"); - TypeHandle elementType = BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[0]); + ITypeHandle elementType = BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[0]); CorElementType et = (CorElementType)ReadLittleEndian(pTopLevel->elementType); int rank = (int)ReadLittleEndian(pTopLevel->ArrayTypeData_arrayRank); - return rts.GetConstructedType(elementType, et, rank, ImmutableArray.Empty); + return rts.GetConstructedType(elementType, et, rank, ImmutableArray.Empty); } - private TypeHandle GetExactPtrOrByRefTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) + private ITypeHandle GetExactPtrOrByRefTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) { if (pArgInfo->m_nEntries != 1) throw new ArgumentException($"Pointer or byref type with arg count: {pArgInfo->m_nEntries}"); - TypeHandle referent = BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[0]); + ITypeHandle referent = BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[0]); CorElementType et = (CorElementType)ReadLittleEndian(pTopLevel->elementType); - return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } - private TypeHandle GetExactClassTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) + private ITypeHandle GetExactClassTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) { ulong vmAssembly = ReadLittleEndian(pTopLevel->ClassTypeData_vmAssembly); uint metadataToken = ReadLittleEndian(pTopLevel->ClassTypeData_metadataToken); - TypeHandle typeConstructor = LookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + ITypeHandle typeConstructor = LookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); int argCount = pArgInfo->m_nEntries; if (argCount == 0) return typeConstructor; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); for (int i = 0; i < argCount; i++) builder.Add(BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[i])); return rts.GetConstructedType(typeConstructor, CorElementType.GenericInst, 0, builder.MoveToImmutable()); } - private TypeHandle GetExactFnPtrTypeHandle(IRuntimeTypeSystem rts, ArgInfoList* pArgInfo) + private ITypeHandle GetExactFnPtrTypeHandle(IRuntimeTypeSystem rts, ArgInfoList* pArgInfo) { int argCount = pArgInfo->m_nEntries; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); for (int i = 0; i < argCount; i++) builder.Add(BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[i])); @@ -3066,13 +3066,13 @@ public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, ui *pcGenericClassTypeParams = 0; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; Contracts.MethodDescHandle pRepMethod = rts.GetMethodDescHandle(vmMethodDesc); - TypeHandle thRepMt = rts.GetTypeHandle(rts.GetMethodTable(pRepMethod)); + ITypeHandle thRepMt = rts.GetTypeHandle(rts.GetMethodTable(pRepMethod)); // Try to resolve exact instantiations using the generics token. Fall back // to canonical when the token is unavailable, the method isn't shared, or any // resolution step fails (analogous to native's SanityCheck path). Contracts.MethodDescHandle pSpecificMethod = pRepMethod; - TypeHandle thSpecificClass = thRepMt; + ITypeHandle thSpecificClass = thRepMt; bool isExact = false; GenericContextLoc ctxLoc = rts.GetGenericContextLoc(pRepMethod); @@ -3101,8 +3101,8 @@ public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, ui { // AcquiresInstMethodTableFromThis: token is some MethodTable*; it may be a // subclass, so walk the parent chain to find the exact declaring class. - TypeHandle thFromThis = rts.GetTypeHandle(new TargetPointer(genericsToken)); - TypeHandle thMatch = GetMethodTableMatchingParentClass(rts, thFromThis, thRepMt); + ITypeHandle thFromThis = rts.GetTypeHandle(new TargetPointer(genericsToken)); + ITypeHandle thMatch = GetMethodTableMatchingParentClass(rts, thFromThis, thRepMt); if (!thMatch.IsNull) { thSpecificClass = thMatch; @@ -3125,19 +3125,19 @@ public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, ui // Project the specific class onto the method's declaring class to get the class instantiation. TargetPointer specMethodMtPtr = rts.GetMethodTable(pSpecificMethod); - TypeHandle thSpecMethodMt = rts.GetTypeHandle(specMethodMtPtr); - TypeHandle thMatchingParent = GetMethodTableMatchingParentClass(rts, thSpecificClass, thSpecMethodMt); - ReadOnlySpan classInst = thMatchingParent.IsNull - ? ReadOnlySpan.Empty + ITypeHandle thSpecMethodMt = rts.GetTypeHandle(specMethodMtPtr); + ITypeHandle thMatchingParent = GetMethodTableMatchingParentClass(rts, thSpecificClass, thSpecMethodMt); + ReadOnlySpan classInst = thMatchingParent.IsNull + ? ReadOnlySpan.Empty : rts.GetInstantiation(thMatchingParent); - ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(pSpecificMethod); + ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(pSpecificMethod); cClassParams = (uint)classInst.Length; *pcGenericClassTypeParams = cClassParams; - // Resolve the System.__Canon TypeHandle for per-parameter fallback. + // Resolve the System.__Canon ITypeHandle for per-parameter fallback. TargetPointer canonMtPtr = rts.GetWellKnownMethodTable(WellKnownMethodTable.Canon); - TypeHandle thCanon = rts.GetTypeHandle(canonMtPtr); + ITypeHandle thCanon = rts.GetTypeHandle(canonMtPtr); DebuggerIPCE_ExpandedTypeData entry; for (int i = 0; i < classInst.Length; i++) @@ -3353,15 +3353,15 @@ public int GetEnCHangingFieldInfo(EnCHangingFieldInfo* pEnCFieldInfo, FieldData* return hr; } - internal TypeHandle LookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) + internal ITypeHandle LookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) { - TypeHandle th = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + ITypeHandle th = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); if (th.IsNull) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; return th; } - internal TypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) + internal ITypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) { ILoader loader = _target.Contracts.Loader; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; @@ -3397,8 +3397,8 @@ public int EnumerateTypeHandleParams(ulong vmTypeHandle, throw new ArgumentNullException(nameof(fpCallback)); IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ITypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); DebuggerIPCE_ExpandedTypeData entry; for (int i = 0; i < instantiation.Length; i++) @@ -3474,7 +3474,7 @@ public int GetSimpleType(int simpleType, uint* pMetadataToken, ulong* pVmModule) try { Contracts.IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = rts.GetPrimitiveType((CorElementType)simpleType); + Contracts.ITypeHandle typeHandle = rts.GetPrimitiveType((CorElementType)simpleType); if (typeHandle.IsNull) { @@ -3530,7 +3530,7 @@ public int IsExceptionObject(ulong vmObject, Interop.BOOL* pResult) break; } - TypeHandle typeHandle = rts.GetTypeHandle(parentMT); + ITypeHandle typeHandle = rts.GetTypeHandle(parentMT); parentMT = rts.GetParentMethodTable(typeHandle); } } @@ -3716,7 +3716,7 @@ public int GetTypedByRefInfo(ulong pTypedByRef, ulong* pObjRef, DebuggerIPCE_Bas { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TypedByRefInfo info = rts.GetTypedByRefInfo(pTypedByRef); - TypeHandle th = rts.GetTypeHandle(info.TypeHandle); + ITypeHandle th = rts.GetTypeHandle(info.ITypeHandle); FillBasicTypeInfo(rts, th, out DebuggerIPCE_BasicTypeData typeData); *pTypedByRefType = typeData; *pObjRef = info.Data.Value; @@ -3754,7 +3754,7 @@ public int GetStringData(ulong objectAddress, uint* pLength, uint* pOffsetToStri { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = _target.Contracts.Object.GetMethodTableAddress(objectAddress); - TypeHandle th = rts.GetTypeHandle(mtAddr); + ITypeHandle th = rts.GetTypeHandle(mtAddr); if (!rts.IsString(th)) { throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_TARGET_INCONSISTENT)!; @@ -3793,7 +3793,7 @@ public int GetArrayData(ulong objectAddress, Interop.BOOL* pIsValidArray, DacDbi IObject objectContract = _target.Contracts.Object; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mt = objectContract.GetMethodTableAddress(objectAddress); - TypeHandle th = rts.GetTypeHandle(mt); + ITypeHandle th = rts.GetTypeHandle(mt); if (rts.IsArray(th, out uint rank)) { TargetPointer dataStart = objectContract.GetArrayData(objectAddress, out uint numComponents, out TargetPointer boundsStart, out TargetPointer lowerBounds); @@ -3856,7 +3856,7 @@ public int GetBasicObjectInfo(ulong objectAddress, Interop.BOOL* pIsValidRef, ui *pObjTypeData = default; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; // verify the object reference is readable and has a valid MethodTable - TypeHandle th = default; + ITypeHandle th = default; try { TargetPointer mt = _target.Contracts.Object.GetMethodTableAddress(objectAddress); @@ -4716,7 +4716,7 @@ public int GetObjectFields(ulong id, uint celt, COR_FIELD* layout, uint* pceltFe throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer(id)); + ITypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer(id)); if (rts.IsTypeDesc(typeHandle)) throw new ArgumentException("TypeDescs are not supported", nameof(id)); @@ -4728,7 +4728,7 @@ public int GetObjectFields(ulong id, uint celt, COR_FIELD* layout, uint* pceltFe TargetPointer parentMT = rts.GetParentMethodTable(typeHandle); if (parentMT != TargetPointer.Null) { - TypeHandle parentHandle = rts.GetTypeHandle(parentMT); + ITypeHandle parentHandle = rts.GetTypeHandle(parentMT); cFields -= rts.GetNumInstanceFields(parentHandle); } @@ -4769,7 +4769,7 @@ public int GetObjectFields(ulong id, uint celt, COR_FIELD* layout, uint* pceltFe // Resolve metadata for this field's enclosing class (for offset lookup and // signature decoding context). TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fieldDescPtr); - TypeHandle enclosingTypeHandle = rts.GetTypeHandle(enclosingMT); + ITypeHandle enclosingTypeHandle = rts.GetTypeHandle(enclosingMT); TargetPointer enclosingModulePtr = rts.GetModule(enclosingTypeHandle); Contracts.ModuleHandle enclosingModuleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(enclosingModulePtr); MetadataReader enclosingMdReader = ecmaMetadataContract.GetMetadata(enclosingModuleHandle)!; @@ -4781,10 +4781,10 @@ public int GetObjectFields(ulong id, uint celt, COR_FIELD* layout, uint* pceltFe // Resolve the field's type. If we cannot decode the signature (e.g. corrupt // metadata or a type that cannot be loaded), zero out the type id and // fieldType, matching native DAC behavior when LookupFieldTypeHandle returns - // a null TypeHandle. + // a null ITypeHandle. try { - TypeHandle fieldTypeHandle = signature.DecodeFieldSignature(fieldDef.Signature, enclosingModuleHandle, enclosingTypeHandle); + ITypeHandle fieldTypeHandle = signature.DecodeFieldSignature(fieldDef.Signature, enclosingModuleHandle, enclosingTypeHandle); if (fieldTypeHandle.IsNull) { corField->id = default; @@ -4802,7 +4802,7 @@ public int GetObjectFields(ulong id, uint celt, COR_FIELD* layout, uint* pceltFe else { // - Pointer/FnPtr typedescs report ELEMENT_TYPE_U's MethodTable. - TypeHandle mtHandle = (signatureType == CorElementType.Ptr || signatureType == CorElementType.FnPtr) + ITypeHandle mtHandle = (signatureType == CorElementType.Ptr || signatureType == CorElementType.FnPtr) ? rts.GetPrimitiveType(CorElementType.U) : fieldTypeHandle; @@ -4813,7 +4813,7 @@ public int GetObjectFields(ulong id, uint celt, COR_FIELD* layout, uint* pceltFe } catch (System.Exception) { - // Field type could not be resolved - mirror native's null-TypeHandle path. + // Field type could not be resolved - mirror native's null-ITypeHandle path. corField->id = default; corField->fieldType = 0; } @@ -4867,7 +4867,7 @@ public int GetTypeLayout(ulong id, COR_TYPE_LAYOUT* pLayout) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer((ulong)id)); + ITypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer((ulong)id)); TargetPointer parentMT = rts.GetParentMethodTable(typeHandle); pLayout->parentID.token1 = parentMT.Value; @@ -4876,7 +4876,7 @@ public int GetTypeLayout(ulong id, COR_TYPE_LAYOUT* pLayout) ushort numInstanceFields = rts.GetNumInstanceFields(typeHandle); if (parentMT != TargetPointer.Null) { - TypeHandle parentHandle = rts.GetTypeHandle(parentMT); + ITypeHandle parentHandle = rts.GetTypeHandle(parentMT); numInstanceFields -= rts.GetNumInstanceFields(parentHandle); } pLayout->numFields = numInstanceFields; @@ -4923,12 +4923,12 @@ public int GetArrayLayout(ulong id, COR_ARRAY_LAYOUT* pLayout) if (id == 0) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle arrayOrStringTypeHandle = rts.GetTypeHandle(new TargetPointer(id)); + ITypeHandle arrayOrStringTypeHandle = rts.GetTypeHandle(new TargetPointer(id)); uint pointerSize = (uint)_target.PointerSize; if (rts.IsString(arrayOrStringTypeHandle)) { - TypeHandle charTypeHandle = rts.GetPrimitiveType(CorElementType.Char); + ITypeHandle charTypeHandle = rts.GetPrimitiveType(CorElementType.Char); pLayout->componentID.token1 = charTypeHandle.Address.Value; pLayout->componentID.token2 = 0; pLayout->componentType = CorElementType.Char; @@ -4944,7 +4944,7 @@ public int GetArrayLayout(ulong id, COR_ARRAY_LAYOUT* pLayout) if (!rts.IsArray(arrayOrStringTypeHandle, out uint rank)) throw Marshal.GetExceptionForHR(HResults.E_INVALIDARG)!; - TypeHandle componentTypeHandle = rts.GetTypeParam(arrayOrStringTypeHandle); + ITypeHandle componentTypeHandle = rts.GetTypeParam(arrayOrStringTypeHandle); CorElementType componentType = rts.IsString(componentTypeHandle) ? CorElementType.String : rts.GetInternalCorElementType(componentTypeHandle); pLayout->componentID.token1 = componentTypeHandle.Address.Value; pLayout->componentID.token2 = 0; @@ -5405,7 +5405,7 @@ public int GetDelegateFunctionData(ulong delegateObject, ulong* ppFunctionAssemb *pMethodDef = rts.GetMethodToken(mdHandle); TargetPointer mtPtr = rts.GetMethodTable(mdHandle); - TypeHandle typeHandle = rts.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = rts.GetTypeHandle(mtPtr); TargetPointer modulePtr = rts.GetModule(typeHandle); Contracts.ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); *ppFunctionAssembly = _target.Contracts.Loader.GetAssembly(moduleHandle).Value; @@ -5470,7 +5470,7 @@ private bool IsDelegateHelper(ulong vmObject) { TargetPointer mt = _target.Contracts.Object.GetMethodTableAddress(vmObject); IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle typeHandle = rts.GetTypeHandle(mt); + ITypeHandle typeHandle = rts.GetTypeHandle(mt); return rts.IsDelegate(typeHandle); } @@ -5755,7 +5755,7 @@ public int GetGenericArgTokenIndex(ulong vmMethod, uint* pIndex) } // Fills a DebuggerIPCE_ExpandedTypeData entry for a single type parameter, falling back to System.__Canon on failure. - private void FillExpandedTypeDataWithCanonFallback(IRuntimeTypeSystem rts, TypeHandle typeHandle, TypeHandle thCanon, DebuggerIPCE_ExpandedTypeData* pTypeInfo) + private void FillExpandedTypeDataWithCanonFallback(IRuntimeTypeSystem rts, ITypeHandle typeHandle, ITypeHandle thCanon, DebuggerIPCE_ExpandedTypeData* pTypeInfo) { try { @@ -5769,7 +5769,7 @@ private void FillExpandedTypeDataWithCanonFallback(IRuntimeTypeSystem rts, TypeH // True if `a` and `b` share the same non-zero TypeDef RID and Module. // Mirrors native MethodTable::HasSameTypeDefAs. - private static bool HasSameTypeDefAs(IRuntimeTypeSystem rts, TypeHandle a, TypeHandle b) + private static bool HasSameTypeDefAs(IRuntimeTypeSystem rts, ITypeHandle a, ITypeHandle b) { if (a.Address == b.Address) return true; @@ -5783,9 +5783,9 @@ private static bool HasSameTypeDefAs(IRuntimeTypeSystem rts, TypeHandle a, TypeH // Walks the parent chain of `start` and returns the first MethodTable whose TypeDef matches `parent`, // or default if no match is found. The walk is bounded by a hard iteration cap to defend against // cycles observed in corrupt dumps. Mirrors native MethodTable::GetMethodTableMatchingParentClass. - private static TypeHandle GetMethodTableMatchingParentClass(IRuntimeTypeSystem rts, TypeHandle start, TypeHandle parent) + private static ITypeHandle GetMethodTableMatchingParentClass(IRuntimeTypeSystem rts, ITypeHandle start, ITypeHandle parent) { - TypeHandle current = start; + ITypeHandle current = start; TargetPointer prev = TargetPointer.Null; for (int i = 0; i < 1000 && !current.IsNull; i++) { @@ -5801,7 +5801,7 @@ private static TypeHandle GetMethodTableMatchingParentClass(IRuntimeTypeSystem r } // Shared core implementation for TypeHandleToExpandedTypeInfo and GetObjectExpandedTypeInfo. - private void TypeHandleToExpandedTypeInfoImpl(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, TypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) + private void TypeHandleToExpandedTypeInfoImpl(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, ITypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) { *pTypeInfo = default; CorElementType elementType = GetElementType(rts, typeHandle); @@ -5848,7 +5848,7 @@ private void TypeHandleToExpandedTypeInfoImpl(IRuntimeTypeSystem rts, AreValueTy // Determines the CorElementType for a type handle, mapping System.Object and System.String // to their specific element types (the runtime's GetSignatureCorElementType returns E_T_CLASS // for both Object and String). - private static CorElementType GetElementType(IRuntimeTypeSystem rts, TypeHandle typeHandle) + private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle typeHandle) { if (typeHandle.IsNull) return CorElementType.Void; @@ -5862,9 +5862,9 @@ private static CorElementType GetElementType(IRuntimeTypeSystem rts, TypeHandle return rts.GetSignatureCorElementType(typeHandle); } - // Mirrors native TypeHandle::UpCastTypeIfNeeded — for continuation types, returns the + // Mirrors native ITypeHandle::UpCastTypeIfNeeded — for continuation types, returns the // parent (continuation base) type handle instead. - private static TypeHandle UpCastTypeIfNeeded(IRuntimeTypeSystem rts, TypeHandle typeHandle) + private static ITypeHandle UpCastTypeIfNeeded(IRuntimeTypeSystem rts, ITypeHandle typeHandle) { if (rts.IsContinuationWithoutMetadata(typeHandle)) { @@ -5877,17 +5877,17 @@ private static TypeHandle UpCastTypeIfNeeded(IRuntimeTypeSystem rts, TypeHandle // Fills ArrayTypeData for E_T_ARRAY and E_T_SZARRAY. // Mirrors native DacDbiInterfaceImpl::GetArrayTypeInfo. - private void FillArrayTypeInfo(IRuntimeTypeSystem rts, TypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) + private void FillArrayTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) { Debug.Assert(rts.IsArray(typeHandle, out _)); rts.IsArray(typeHandle, out uint rank); WriteLittleEndian(ref pTypeInfo->ArrayTypeData_arrayRank, rank); - TypeHandle elemTypeHandle = rts.GetTypeParam(typeHandle); + ITypeHandle elemTypeHandle = rts.GetTypeParam(typeHandle); FillBasicTypeInfo(rts, elemTypeHandle, out pTypeInfo->ArrayTypeData_arrayTypeArg); } // Fills UnaryTypeData for E_T_PTR and E_T_BYREF (or ClassTypeData if AllBoxed). - private void FillPtrTypeInfo(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, TypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) + private void FillPtrTypeInfo(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, ITypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) { if (boxed == AreValueTypesBoxed.AllBoxed) { @@ -5895,13 +5895,13 @@ private void FillPtrTypeInfo(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, T } else { - TypeHandle paramTypeHandle = rts.GetTypeParam(typeHandle); + ITypeHandle paramTypeHandle = rts.GetTypeParam(typeHandle); FillBasicTypeInfo(rts, paramTypeHandle, out pTypeInfo->UnaryTypeData_unaryTypeArg); } } // Fills ClassTypeData for E_T_CLASS and E_T_VALUETYPE. - private void FillClassTypeInfo(IRuntimeTypeSystem rts, TypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) + private void FillClassTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) { typeHandle = UpCastTypeIfNeeded(rts, typeHandle); @@ -5909,7 +5909,7 @@ private void FillClassTypeInfo(IRuntimeTypeSystem rts, TypeHandle typeHandle, De Contracts.ILoader loader = _target.Contracts.Loader; Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length > 0) { // Generic instantiation — set the type handle so the debugger can fetch type arguments @@ -5924,7 +5924,7 @@ private void FillClassTypeInfo(IRuntimeTypeSystem rts, TypeHandle typeHandle, De } // Fills NaryTypeData for E_T_FNPTR (or ClassTypeData if AllBoxed). - private void FillFnPtrTypeInfo(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, TypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) + private void FillFnPtrTypeInfo(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, ITypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) { if (boxed == AreValueTypesBoxed.AllBoxed) { @@ -5938,8 +5938,8 @@ private void FillFnPtrTypeInfo(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, // Fills a DebuggerIPCE_BasicTypeData for a type handle — used for array element types // and ptr/byref referent types. Exposed as internal so tests can build the ArgInfoList - // needed to round-trip a TypeHandle through GetExactTypeHandle. - internal void FillBasicTypeInfo(IRuntimeTypeSystem rts, TypeHandle typeHandle, out DebuggerIPCE_BasicTypeData typeInfo) + // needed to round-trip a ITypeHandle through GetExactTypeHandle. + internal void FillBasicTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, out DebuggerIPCE_BasicTypeData typeInfo) { typeInfo = default; CorElementType elementType = GetElementType(rts, typeHandle); @@ -5965,7 +5965,7 @@ internal void FillBasicTypeInfo(IRuntimeTypeSystem rts, TypeHandle typeHandle, o Contracts.ILoader loader = _target.Contracts.Loader; Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length > 0) { WriteLittleEndian(ref typeInfo.vmTypeHandle, typeHandle.Address.Value); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/Helpers/HeapWalk.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/Helpers/HeapWalk.cs index 4910f02297cc15..2c37d79e783aa5 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/Helpers/HeapWalk.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/Helpers/HeapWalk.cs @@ -113,7 +113,7 @@ private bool TryGetObjectSize(TargetPointer objAddr, TargetPointer mt, out ulong size = 0; try { - TypeHandle handle = _rts.GetTypeHandle(mt); + ITypeHandle handle = _rts.GetTypeHandle(mt); ulong baseSize = _rts.GetBaseSize(handle); uint componentSize = _rts.GetComponentSize(handle); uint numComponentsOffset = 0; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs index cc96dd9fc20abd..c97ead7bc9431f 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs @@ -375,7 +375,7 @@ public struct DebuggerIPCE_BasicTypeData [FieldOffset(0)] public int elementType; // Portable [FieldOffset(4)] public uint metadataToken; // Portable [FieldOffset(8)] public ulong vmAssembly; // VMPTR_Assembly (Portable) - [FieldOffset(16)] public ulong vmTypeHandle; // VMPTR_TypeHandle (Portable) + [FieldOffset(16)] public ulong vmTypeHandle; // VMPTR_ITypeHandle (Portable) } [StructLayout(LayoutKind.Sequential)] @@ -398,7 +398,7 @@ public struct DebuggerIPCE_ExpandedTypeData // ClassTypeData (used for E_T_CLASS, E_T_VALUETYPE) [FieldOffset(8)] public uint ClassTypeData_metadataToken; // Portable [FieldOffset(16)] public ulong ClassTypeData_vmAssembly; // VMPTR_Assembly - [FieldOffset(24)] public ulong ClassTypeData_typeHandle; // VMPTR_TypeHandle + [FieldOffset(24)] public ulong ClassTypeData_typeHandle; // VMPTR_ITypeHandle // UnaryTypeData (used for E_T_PTR, E_T_BYREF) — overlaps union at offset 8 [FieldOffset(8)] public DebuggerIPCE_BasicTypeData UnaryTypeData_unaryTypeArg; @@ -408,7 +408,7 @@ public struct DebuggerIPCE_ExpandedTypeData [FieldOffset(32)] public uint ArrayTypeData_arrayRank; // Portable // NaryTypeData (used for E_T_FNPTR) — overlaps union at offset 8 - [FieldOffset(8)] public ulong NaryTypeData_typeHandle; // VMPTR_TypeHandle + [FieldOffset(8)] public ulong NaryTypeData_typeHandle; // VMPTR_ITypeHandle } [StructLayout(LayoutKind.Sequential)] @@ -709,7 +709,7 @@ public unsafe partial interface IDacDbiInterface int EnumerateInstantiationFields(ulong vmAssembly, ulong vmThExact, ulong vmThApprox, nuint* pObjectSize, delegate* unmanaged fpCallback, nint pUserData); [PreserveSig] - int TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, ulong vmTypeHandle, DebuggerIPCE_ExpandedTypeData* pData); + int ITypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, ulong vmTypeHandle, DebuggerIPCE_ExpandedTypeData* pData); [PreserveSig] int GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, ulong addr, DebuggerIPCE_ExpandedTypeData* pTypeInfo); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs index 85bd1ad8f10c26..387a58ea375bc0 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs @@ -298,7 +298,7 @@ private IEnumerable IterateMethodInstantiations(Contracts.Modu } } - private IEnumerable IterateTypeParams(Contracts.ModuleHandle moduleHandle) + private IEnumerable IterateTypeParams(Contracts.ModuleHandle moduleHandle) { IEnumerable typeParams = _loader.GetAvailableTypeParams(moduleHandle); @@ -345,7 +345,7 @@ 4. Generic method on Generic type (There are N generic defining methods where N } TargetPointer mtAddr = _rts.GetMethodTable(mainMD); - TypeHandle mainMT = _rts.GetTypeHandle(mtAddr); + ITypeHandle mainMT = _rts.GetTypeHandle(mtAddr); TargetPointer mainModule = _rts.GetModule(mainMT); uint mainMTToken = _rts.GetTypeDefToken(mainMT); uint mainMDToken = _rts.GetMethodToken(mainMD); @@ -359,7 +359,7 @@ 4. Generic method on Generic type (There are N generic defining methods where N { foreach (MethodDescHandle methodDesc in IterateMethodInstantiations(moduleHandle)) { - TypeHandle methodTypeHandle = _rts.GetTypeHandle(_rts.GetMethodTable(methodDesc)); + ITypeHandle methodTypeHandle = _rts.GetTypeHandle(_rts.GetMethodTable(methodDesc)); if (mainModule != _rts.GetModule(methodTypeHandle)) continue; if (mainMDToken != _rts.GetMethodToken(methodDesc)) continue; @@ -382,7 +382,7 @@ 4. Generic method on Generic type (There are N generic defining methods where N { if (HasClassInstantiation(mainMD)) { - foreach (Contracts.TypeHandle typeParam in IterateTypeParams(moduleHandle)) + foreach (Contracts.ITypeHandle typeParam in IterateTypeParams(moduleHandle)) { uint typeParamToken = _rts.GetTypeDefToken(typeParam); @@ -396,7 +396,7 @@ 4. Generic method on Generic type (There are N generic defining methods where N if (mainModule != _rts.GetModule(typeParam)) continue; TargetPointer cmt = _rts.GetCanonicalMethodTable(typeParam); - TypeHandle cmtHandle = _rts.GetTypeHandle(cmt); + ITypeHandle cmtHandle = _rts.GetTypeHandle(cmt); TargetPointer methodDescAddr = _rts.GetMethodDescForSlot(cmtHandle, slotNum); if (methodDescAddr == TargetPointer.Null) continue; @@ -425,7 +425,7 @@ private bool HasClassInstantiation(MethodDescHandle md) IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = rts.GetMethodTable(md); - TypeHandle mt = rts.GetTypeHandle(mtAddr); + ITypeHandle mt = rts.GetTypeHandle(mtAddr); return !rts.GetInstantiation(mt).IsEmpty; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs index 6d03e9990c2440..af7656416b35f5 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs @@ -1067,19 +1067,19 @@ int ISOSDacInterface.GetFieldDescData(ClrDataAddress fieldDesc, DacpFieldDescDat FieldDefinitionHandle fieldHandle = (FieldDefinitionHandle)MetadataTokens.Handle((int)token); TargetPointer enclosingMT = rtsContract.GetMTOfEnclosingClass(fieldDescTargetPtr); - TypeHandle ctx = rtsContract.GetTypeHandle(enclosingMT); + ITypeHandle ctx = rtsContract.GetTypeHandle(enclosingMT); TargetPointer modulePtr = rtsContract.GetModule(ctx); Contracts.ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); MetadataReader mdReader = ecmaMetadataContract.GetMetadata(moduleHandle)!; FieldDefinition fieldDef = mdReader.GetFieldDefinition(fieldHandle); - TypeHandle foundTypeHandle = rtsContract.GetFieldDescApproxTypeHandle(fieldDescTargetPtr); + ITypeHandle foundTypeHandle = rtsContract.GetFieldDescApproxTypeHandle(fieldDescTargetPtr); try { // get the MT of the type // This is an implementation detail of the DAC that we replicate here to get method tables for non-MT types // that we can return to SOS for pretty-printing. - // In the future we may want to return a TypeHandle instead of a MethodTable, and modify SOS to do more complete pretty-printing. + // In the future we may want to return an ITypeHandle instead of a MethodTable, and modify SOS to do more complete pretty-printing. // DAC equivalent: src/coreclr/vm/typehandle.inl TypeHandle::GetMethodTable if (foundTypeHandle.IsNull) // if we can't find the MT (e.g in a minidump) @@ -1092,7 +1092,7 @@ int ISOSDacInterface.GetFieldDescData(ClrDataAddress fieldDesc, DacpFieldDescDat else if (rtsContract.HasTypeParam(foundTypeHandle)) { // value typedescs - TypeHandle paramTypeHandle = rtsContract.GetTypeParam(foundTypeHandle); + ITypeHandle paramTypeHandle = rtsContract.GetTypeParam(foundTypeHandle); data->MTOfType = paramTypeHandle.Address.ToClrDataAddress(_target); } else @@ -2317,7 +2317,7 @@ int ISOSDacInterface.GetMethodDescData(ClrDataAddress addr, ClrDataAddress ip, D data->MethodDescPtr = addr; TargetPointer methodTableAddr = rtsContract.GetMethodTable(methodDescHandle); data->MethodTablePtr = methodTableAddr.ToClrDataAddress(_target); - TypeHandle typeHandle = rtsContract.GetTypeHandle(methodTableAddr); + ITypeHandle typeHandle = rtsContract.GetTypeHandle(methodTableAddr); data->ModulePtr = rtsContract.GetModule(typeHandle).ToClrDataAddress(_target); // If rejit info is appropriate, get the following: @@ -2793,7 +2793,7 @@ int ISOSDacInterface.GetMethodTableData(ClrDataAddress mt, DacpMethodTableData* if (mt == 0 || data == null) throw new ArgumentException(); Contracts.IRuntimeTypeSystem contract = _target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle methodTable = contract.GetTypeHandle(mt.ToTargetPointer(_target)); + Contracts.ITypeHandle methodTable = contract.GetTypeHandle(mt.ToTargetPointer(_target)); DacpMethodTableData result = default; result.baseSize = contract.GetBaseSize(methodTable); @@ -2866,7 +2866,7 @@ int ISOSDacInterface.GetMethodTableFieldData(ClrDataAddress mt, DacpMethodTableF TargetPointer mtAddress = mt.ToTargetPointer(_target); Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; - TypeHandle typeHandle = rtsContract.GetTypeHandle(mtAddress); + ITypeHandle typeHandle = rtsContract.GetTypeHandle(mtAddress); data->FirstField = rtsContract.GetFieldDescList(typeHandle).FirstOrDefault().ToClrDataAddress(_target); data->wNumInstanceFields = rtsContract.GetNumInstanceFields(typeHandle); data->wNumStaticFields = rtsContract.GetNumStaticFields(typeHandle); @@ -2906,7 +2906,7 @@ int ISOSDacInterface.GetMethodTableForEEClass(ClrDataAddress eeClassReallyCanonM if (eeClassReallyCanonMT == 0 || value == null) throw new ArgumentException(); Contracts.IRuntimeTypeSystem contract = _target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle methodTableHandle = contract.GetTypeHandle(eeClassReallyCanonMT.ToTargetPointer(_target)); + Contracts.ITypeHandle methodTableHandle = contract.GetTypeHandle(eeClassReallyCanonMT.ToTargetPointer(_target)); *value = methodTableHandle.Address.ToClrDataAddress(_target); } catch (global::System.Exception ex) @@ -2936,7 +2936,7 @@ int ISOSDacInterface.GetMethodTableName(ClrDataAddress mt, uint count, char* mtN throw new ArgumentException(); Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem; Contracts.ILoader loader = _target.Contracts.Loader; - Contracts.TypeHandle methodTableHandle = typeSystemContract.GetTypeHandle(mt.ToTargetPointer(_target, overrideCheck: true)); + Contracts.ITypeHandle methodTableHandle = typeSystemContract.GetTypeHandle(mt.ToTargetPointer(_target, overrideCheck: true)); if (typeSystemContract.IsFreeObjectMethodTable(methodTableHandle)) { OutputBufferHelpers.CopyStringToBuffer(mtName, count, pNeeded, "Free"); @@ -3008,7 +3008,7 @@ int ISOSDacInterface.GetMethodTableSlot(ClrDataAddress mt, uint slot, ClrDataAdd throw new ArgumentException(); TargetPointer methodTable = mt.ToTargetPointer(_target); - TypeHandle methodTableHandle = rts.GetTypeHandle(methodTable); // validate MT + ITypeHandle methodTableHandle = rts.GetTypeHandle(methodTable); // validate MT ushort vtableSlots = rts.GetNumVtableSlots(methodTableHandle); @@ -3251,7 +3251,7 @@ int ISOSDacInterface.GetObjectClassName(ClrDataAddress obj, uint count, char* cl Contracts.ILoader loader = _target.Contracts.Loader; TargetPointer mt = objectContract.GetMethodTableAddress(obj.ToTargetPointer(_target)); - Contracts.TypeHandle typeHandle = rts.GetTypeHandle(mt); + Contracts.ITypeHandle typeHandle = rts.GetTypeHandle(mt); TargetPointer modulePointer = rts.GetModule(typeHandle); if (modulePointer == TargetPointer.Null) @@ -3323,7 +3323,7 @@ int ISOSDacInterface.GetObjectData(ClrDataAddress objAddr, DacpObjectData* data) TargetPointer objPtr = objAddr.ToTargetPointer(_target); TargetPointer mt = objectContract.GetMethodTableAddress(objPtr); - TypeHandle handle = runtimeTypeSystemContract.GetTypeHandle(mt); + ITypeHandle handle = runtimeTypeSystemContract.GetTypeHandle(mt); data->MethodTable = mt.ToClrDataAddress(_target); data->Size = runtimeTypeSystemContract.GetBaseSize(handle); @@ -3365,7 +3365,7 @@ int ISOSDacInterface.GetObjectData(ClrDataAddress objAddr, DacpObjectData* data) data->Size += numComponents * data->dwComponentSize; // Get the type of the array elements - TypeHandle element = runtimeTypeSystemContract.GetTypeParam(handle); + ITypeHandle element = runtimeTypeSystemContract.GetTypeParam(handle); data->ElementTypeHandle = element.Address.Value; data->ElementType = (uint)runtimeTypeSystemContract.GetSignatureCorElementType(element); @@ -5424,7 +5424,7 @@ int ISOSDacInterface6.GetMethodTableCollectibleData(ClrDataAddress mt, DacpMetho Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; ILoader loaderContract = _target.Contracts.Loader; - Contracts.TypeHandle typeHandle = rtsContract.GetTypeHandle(mt.ToTargetPointer(_target)); + Contracts.ITypeHandle typeHandle = rtsContract.GetTypeHandle(mt.ToTargetPointer(_target)); bool isCollectible = rtsContract.IsCollectible(typeHandle); if (isCollectible) @@ -5578,7 +5578,7 @@ int ISOSDacInterface7.GetProfilerModifiedILInformation(ClrDataAddress methodDesc // getting the module handle and the token from the method desc MethodDescHandle mdh = rts.GetMethodDescHandle(methodDescPtr); TargetPointer mt = rts.GetMethodTable(mdh); - TypeHandle typeHandle = rts.GetTypeHandle(mt); + ITypeHandle typeHandle = rts.GetTypeHandle(mt); TargetPointer modulePtr = rts.GetModule(typeHandle); uint token = rts.GetMethodToken(mdh); Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); @@ -5639,7 +5639,7 @@ int ISOSDacInterface7.GetMethodsWithProfilerModifiedIL(ClrDataAddress mod, ClrDa { if (*pcMethodDescs >= cMethodDescs) break; - TypeHandle typeHandle = rts.GetTypeHandle(ptr); + ITypeHandle typeHandle = rts.GetTypeHandle(ptr); foreach (TargetPointer md in rts.GetIntroducedMethodDescs(typeHandle)) { MethodDescHandle mdh = rts.GetMethodDescHandle(md); @@ -5998,7 +5998,7 @@ int ISOSDacInterface8.GetAssemblyLoadContext(ClrDataAddress methodTable, ClrData Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; Contracts.ILoader loaderContract = _target.Contracts.Loader; - Contracts.TypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); + Contracts.ITypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); Contracts.ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(rtsContract.GetModule(methodTableHandle)); TargetPointer alc = loaderContract.GetAssemblyLoadContext(moduleHandle); *assemblyLoadContext = alc.ToClrDataAddress(_target); @@ -6284,7 +6284,7 @@ int ISOSDacInterface11.IsTrackedType(ClrDataAddress objAddr, Interop.BOOL* isTra throw new ArgumentException(); Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; - TypeHandle mtHandle = rtsContract.GetTypeHandle(mt); + ITypeHandle mtHandle = rtsContract.GetTypeHandle(mt); if (rtsContract.IsTrackedReferenceWithFinalizer(mtHandle)) *isTrackedType = Interop.BOOL.TRUE; @@ -6726,7 +6726,7 @@ int ISOSDacInterface14.GetStaticBaseAddress(ClrDataAddress methodTable, ClrDataA throw new ArgumentException(); Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); + Contracts.ITypeHandle typeHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); if (GCStaticsAddress != null) *GCStaticsAddress = rtsContract.GetGCStaticsBasePointer(typeHandle).ToClrDataAddress(_target); if (nonGCStaticsAddress != null) @@ -6767,7 +6767,7 @@ int ISOSDacInterface14.GetThreadStaticBaseAddress(ClrDataAddress methodTable, Cl Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; TargetPointer methodTablePtr = methodTable.ToTargetPointer(_target); TargetPointer threadPtr = thread.ToTargetPointer(_target); - Contracts.TypeHandle typeHandle = rtsContract.GetTypeHandle(methodTablePtr); + Contracts.ITypeHandle typeHandle = rtsContract.GetTypeHandle(methodTablePtr); ushort numThreadStaticFields = rtsContract.GetNumThreadStaticFields(typeHandle); if (numThreadStaticFields == 0) { @@ -6820,7 +6820,7 @@ int ISOSDacInterface14.GetMethodTableInitializationFlags(ClrDataAddress methodTa throw new NullReferenceException(); Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); + Contracts.ITypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); *initializationStatus = (MethodTableInitializationFlags)0; if (rtsContract.IsClassInited(methodTableHandle)) *initializationStatus = MethodTableInitializationFlags.MethodTableInitialized; @@ -6854,14 +6854,14 @@ internal sealed unsafe partial class SOSMethodEnum : ISOSMethodEnum { private readonly Target _target; private readonly IRuntimeTypeSystem _rts; - private readonly TypeHandle _methodTable; + private readonly ITypeHandle _methodTable; private readonly ISOSMethodEnum? _legacyMethodEnum; private uint _iteratorIndex; private List _methods = []; - public SOSMethodEnum(Target target, TypeHandle methodTable, ISOSMethodEnum? legacyMethodEnum) + public SOSMethodEnum(Target target, ITypeHandle methodTable, ISOSMethodEnum? legacyMethodEnum) { _target = target; _rts = _target.Contracts.RuntimeTypeSystem; @@ -6897,7 +6897,7 @@ private void PopulateMethods() TargetPointer mtAddr = _rts.GetMethodTable(mdh); methodData.DefiningMethodTable = mtAddr.ToClrDataAddress(_target); - TypeHandle typeHandle = _rts.GetTypeHandle(mtAddr); + ITypeHandle typeHandle = _rts.GetTypeHandle(mtAddr); methodData.DefiningModule = _rts.GetModule(typeHandle).ToClrDataAddress(_target); methodData.Token = _rts.GetMethodToken(mdh); } @@ -6921,7 +6921,7 @@ private void PopulateMethods() TargetPointer mtAddr = _rts.GetMethodTable(mdh); methodData.DefiningMethodTable = mtAddr.ToClrDataAddress(_target); - TypeHandle typeHandle = _rts.GetTypeHandle(mtAddr); + ITypeHandle typeHandle = _rts.GetTypeHandle(mtAddr); methodData.DefiningModule = _rts.GetModule(typeHandle).ToClrDataAddress(_target); methodData.Token = _rts.GetMethodToken(mdh); @@ -7040,7 +7040,7 @@ int ISOSDacInterface15.GetMethodTableSlotEnumerator(ClrDataAddress mt, DacComNul throw new ArgumentException(); IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - TypeHandle methodTableHandle = rts.GetTypeHandle(mt.ToTargetPointer(_target)); + ITypeHandle methodTableHandle = rts.GetTypeHandle(mt.ToTargetPointer(_target)); ISOSMethodEnum? legacyMethodEnum = null; #if DEBUG diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs index 6e41501fab87f7..12e8c3d2d1e1e0 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; @@ -18,8 +18,8 @@ public static unsafe void AppendSigFormat(Target target, string? memberName, string? className, string? namespaceName, - ReadOnlySpan typeInstantiation, - ReadOnlySpan methodInstantiation, + ReadOnlySpan typeInstantiation, + ReadOnlySpan methodInstantiation, bool CStringParmsOnly) { fixed (byte* pSignature = signature) @@ -36,8 +36,8 @@ public static void AppendSigFormat(Target target, string? memberName, string? className, string? namespaceName, - ReadOnlySpan typeInstantiation, - ReadOnlySpan methodInstantiation, + ReadOnlySpan typeInstantiation, + ReadOnlySpan methodInstantiation, bool CStringParmsOnly) { SignatureHeader header = signature.ReadSignatureHeader(); @@ -95,8 +95,8 @@ public static void AppendSigFormat(Target target, private static unsafe void AddTypeString(Target target, StringBuilder stringBuilder, ref BlobReader signature, - ReadOnlySpan typeInstantiation, - ReadOnlySpan methodInstantiation, + ReadOnlySpan typeInstantiation, + ReadOnlySpan methodInstantiation, MetadataReader? metadata) { string _namespace; @@ -157,7 +157,7 @@ private static unsafe void AddTypeString(Target target, case CorElementType.Internal: TargetPointer typeHandlePointer = target.ReadPointerFromSpan(signature.ReadBytes(target.PointerSize)); IRuntimeTypeSystem runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; - TypeHandle th = runtimeTypeSystem.GetTypeHandle(typeHandlePointer); + ITypeHandle th = runtimeTypeSystem.GetTypeHandle(typeHandlePointer); switch (runtimeTypeSystem.GetSignatureCorElementType(th)) { case CorElementType.FnPtr: @@ -308,7 +308,7 @@ private static unsafe void AddTypeString(Target target, } } - private static void AddType(Target target, StringBuilder stringBuilder, TypeHandle typeHandle) + private static void AddType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle) { IRuntimeTypeSystem runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; @@ -358,7 +358,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, TypeHand } stringBuilder.Append(name); - ReadOnlySpan instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); if (instantiation.Length > 0) { stringBuilder.Append('<'); @@ -414,7 +414,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, TypeHand return; case CorElementType.FnPtr: - runtimeTypeSystem.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv); + runtimeTypeSystem.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv); SignatureHeader header = new SignatureHeader((byte)callConv); AddType(target, stringBuilder, retAndArgTypes[0]); stringBuilder.Append(" ("); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs index e481d0cc471fe3..0b76140830d9a6 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs @@ -62,12 +62,12 @@ public static void AppendMethodInternal(Target target, StringBuilder stringBuild AppendMethodImpl(target, stringBuilder, method, default, format); } - public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, ReadOnlySpan typeInstantiation, TypeNameFormat format) + public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, ReadOnlySpan typeInstantiation, TypeNameFormat format) { IRuntimeTypeSystem runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; ILoader loader = target.Contracts.Loader; string methodName; - TypeHandle th = default; + ITypeHandle th = default; bool isNoMetadataMethod = runtimeTypeSystem.IsNoMetadataMethod(method, out methodName); if (isNoMetadataMethod) @@ -129,7 +129,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, } } - ReadOnlySpan genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); + ReadOnlySpan genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); if (genericMethodInstantiation.Length > 0 && !runtimeTypeSystem.IsGenericMethodDefinition(method)) { AppendInst(target, stringBuilder, genericMethodInstantiation, format); @@ -142,7 +142,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, runtimeTypeSystem.GetModule(runtimeTypeSystem.GetTypeHandle(runtimeTypeSystem.GetMethodTable(method)))); MetadataReader? reader = target.Contracts.EcmaMetadata.GetMetadata(methodModule); - ReadOnlySpan typeInstantiationSigFormat = default; + ReadOnlySpan typeInstantiationSigFormat = default; if (!th.IsNull) { typeInstantiationSigFormat = runtimeTypeSystem.GetInstantiation(th); @@ -158,9 +158,9 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, } } - public static TypeHandle GetExactOwningType(IRuntimeTypeSystem runtimeTypeSystem, TypeHandle possiblyDerivedType, MethodDescHandle method) + public static ITypeHandle GetExactOwningType(IRuntimeTypeSystem runtimeTypeSystem, ITypeHandle possiblyDerivedType, MethodDescHandle method) { - TypeHandle approxOwner = runtimeTypeSystem.GetTypeHandle(runtimeTypeSystem.GetMethodTable(method)); + ITypeHandle approxOwner = runtimeTypeSystem.GetTypeHandle(runtimeTypeSystem.GetMethodTable(method)); uint typeDefTokenOfOwner = runtimeTypeSystem.GetTypeDefToken(approxOwner); TargetPointer moduleOfOwner = runtimeTypeSystem.GetModule(approxOwner); @@ -184,18 +184,18 @@ public static TypeHandle GetExactOwningType(IRuntimeTypeSystem runtimeTypeSystem } while (true); } - public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.TypeHandle typeHandle, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.ITypeHandle typeHandle, TypeNameFormat format) { AppendType(target, stringBuilder, typeHandle, default, format); } - public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.TypeHandle typeHandle, ReadOnlySpan typeInstantiation, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.ITypeHandle typeHandle, ReadOnlySpan typeInstantiation, TypeNameFormat format) { TypeNameBuilder builder = new(stringBuilder, target, format); AppendTypeCore(ref builder, typeHandle, typeInstantiation, format); } - private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle typeHandle, ReadOnlySpan instantiation, TypeNameFormat format) + private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandle typeHandle, ReadOnlySpan instantiation, TypeNameFormat format) { bool toString = format.HasFlag(TypeNameFormat.FormatNamespace) && !format.HasFlag(TypeNameFormat.FormatFullInst) && !format.HasFlag(TypeNameFormat.FormatAssembly); @@ -212,13 +212,13 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle if (elemType != Contracts.CorElementType.ValueType) { typeSystemContract.IsArray(typeHandle, out uint rank); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), default(ReadOnlySpan), (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), default(ReadOnlySpan), (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); AppendParamTypeQualifier(ref tnb, elemType, rank); } else { tnb.TypeString.Append("VALUETYPE"); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), Array.Empty(), format & ~TypeNameFormat.FormatAssembly); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), Array.Empty(), format & ~TypeNameFormat.FormatAssembly); } } else if (typeSystemContract.IsGenericVariable(typeHandle, out TargetPointer modulePointer, out uint genericParamToken)) @@ -241,7 +241,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle tnb.AddName(reader.GetString(genericParam.Name)); format &= ~TypeNameFormat.FormatAssembly; } - else if (typeSystemContract.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv)) + else if (typeSystemContract.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv)) { if (format.HasFlag(TypeNameFormat.FormatNamespace)) { @@ -299,7 +299,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle if (format.HasFlag(TypeNameFormat.FormatNamespace) || format.HasFlag(TypeNameFormat.FormatAssembly)) { - ReadOnlySpan instantiationSpan = typeSystemContract.GetInstantiation(typeHandle); + ReadOnlySpan instantiationSpan = typeSystemContract.GetInstantiation(typeHandle); if ((instantiationSpan.Length > 0) && (!typeSystemContract.IsGenericTypeDefinition(typeHandle) || toString)) { @@ -329,16 +329,16 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.TypeHandle // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s // and enclose each parameter in square brackets to disambiguate the commas // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion - private static void AppendInst(Target target, StringBuilder stringBuilder, ReadOnlySpan inst, TypeNameFormat format) + private static void AppendInst(Target target, StringBuilder stringBuilder, ReadOnlySpan inst, TypeNameFormat format) { TypeNameBuilder tnb = new(stringBuilder, target, format, initialStateIsName: true); AppendInst(ref tnb, inst, format); } - private static void AppendInst(ref TypeNameBuilder tnb, ReadOnlySpan inst, TypeNameFormat format) + private static void AppendInst(ref TypeNameBuilder tnb, ReadOnlySpan inst, TypeNameFormat format) { tnb.OpenGenericArguments(); - foreach (TypeHandle arg in inst) + foreach (ITypeHandle arg in inst) { tnb.OpenGenericArgument(); if (format.HasFlag(TypeNameFormat.FormatFullInst) && !tnb.Target.Contracts.RuntimeTypeSystem.IsGenericVariable(arg, out _, out _)) @@ -506,7 +506,7 @@ private void AddAssemblySpec(string? assemblySpec) /// Only GC descriptor series whose startoffset is at or above the continuation data /// payload (i.e., after the fixed CORINFO_Continuation header fields) are included. /// - private static void AppendContinuationName(ref TypeNameBuilder tnb, IRuntimeTypeSystem typeSystemContract, TypeHandle typeHandle) + private static void AppendContinuationName(ref TypeNameBuilder tnb, IRuntimeTypeSystem typeSystemContract, ITypeHandle typeHandle) { uint baseSize = typeSystemContract.GetBaseSize(typeHandle); uint continuationDataOffset = tnb.Target.GetTypeInfo(DataType.ContinuationObject).Size!.Value; diff --git a/src/native/managed/cdac/gen/CdacGenerator.cs b/src/native/managed/cdac/gen/CdacGenerator.cs index 2375b2fdb60d05..a93ddd5a835d96 100644 --- a/src/native/managed/cdac/gen/CdacGenerator.cs +++ b/src/native/managed/cdac/gen/CdacGenerator.cs @@ -11,7 +11,7 @@ namespace Microsoft.Diagnostics.DataContractReader.DataGenerator; /// /// Source generator for cdac classes. Emits the /// boilerplate IData<T>.Create factory, managed-type -/// TypeHandle accessors, and static-field accessors from +/// ITypeHandle accessors, and static-field accessors from /// declarative attributes. /// /// diff --git a/src/native/managed/cdac/gen/Emitter.cs b/src/native/managed/cdac/gen/Emitter.cs index 162d75d2ddcce4..3d3e054d901310 100644 --- a/src/native/managed/cdac/gen/Emitter.cs +++ b/src/native/managed/cdac/gen/Emitter.cs @@ -12,10 +12,10 @@ internal static class Emitter // Generated files declare a file-scoped namespace inside // Microsoft.Diagnostics.DataContractReader.* so these short names resolve // via parent-namespace lookup. The using directives below cover - // TypeHandle (in ...Contracts) explicitly. + // ITypeHandle (in ...Contracts) explicitly. private const string Target = "Target"; private const string TargetPointer = "TargetPointer"; - private const string TypeHandleType = "TypeHandle"; + private const string ITypeHandleType = "ITypeHandle"; private const string IDataInterface = "IData"; private const string RootNamespace = "Microsoft.Diagnostics.DataContractReader"; @@ -51,7 +51,7 @@ public static string Emit(CdacTypeModel model) sb.AppendLine($"partial class {model.ClassName}"); sb.AppendLine("{"); - // Emit a static _typeNames array for LayoutSet.Resolve and TypeHandle resolution. + // Emit a static _typeNames array for LayoutSet.Resolve and ITypeHandle resolution. if (model.Names.Count > 0) { string namesLiteral = NamesArrayLiteral(model.Names); @@ -59,10 +59,10 @@ public static string Emit(CdacTypeModel model) sb.AppendLine(); } - // The class advertises a managed identity (TypeHandle) when HasTypeHandle is set. + // The class advertises a managed identity (ITypeHandle) when HasTypeHandle is set. if (model.HasTypeHandle) { - sb.AppendLine($" public static {TypeHandleType} TypeHandle({Target} target)"); + sb.AppendLine($" public static {ITypeHandleType} ITypeHandle({Target} target)"); sb.AppendLine($" => TypeNameResolver.GetTypeHandle(target, _typeNames);"); sb.AppendLine(); } diff --git a/src/native/managed/cdac/gen/TypeNameResolverSource.cs b/src/native/managed/cdac/gen/TypeNameResolverSource.cs index 8d6a7f777eb5af..ff4ecb39206db6 100644 --- a/src/native/managed/cdac/gen/TypeNameResolverSource.cs +++ b/src/native/managed/cdac/gen/TypeNameResolverSource.cs @@ -6,7 +6,7 @@ namespace Microsoft.Diagnostics.DataContractReader.DataGenerator; /// /// Source for the TypeNameResolver helper emitted into each consuming /// assembly via RegisterSourceOutput (gated by CompilationProvider to -/// avoid duplicate symbols). Resolves TypeHandle, static field addresses, and +/// avoid duplicate symbols). Resolves ITypeHandle, static field addresses, and /// thread-static field addresses across a cascade of candidate type names. /// internal static class TypeNameResolverSource @@ -26,15 +26,15 @@ namespace Microsoft.Diagnostics.DataContractReader.Generated; internal static class TypeNameResolver { - public static TypeHandle GetTypeHandle(Target target, string[] names) + public static ITypeHandle GetTypeHandle(Target target, string[] names) { foreach (string name in names) { - if (target.Contracts.ManagedTypeSource.TryGetTypeHandle(name, out TypeHandle th)) + if (target.Contracts.ManagedTypeSource.TryGetTypeHandle(name, out ITypeHandle th)) return th; } throw new InvalidOperationException( - $"No managed type resolved for TypeHandle (names=[{string.Join(",", names)}])."); + $"No managed type resolved for ITypeHandle (names=[{string.Join(",", names)}])."); } public static TargetPointer GetStaticFieldAddress(Target target, string[] names, string fieldName) diff --git a/src/native/managed/cdac/tests/DumpTests/AsyncContinuationDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/AsyncContinuationDumpTests.cs index 14731f6418bf92..33e13d8d052ffc 100644 --- a/src/native/managed/cdac/tests/DumpTests/AsyncContinuationDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/AsyncContinuationDumpTests.cs @@ -44,7 +44,7 @@ public void ContinuationBaseClass_IsNotContinuation(TestConfiguration config) TargetPointer continuationMT = Target.ReadPointer(continuationMTGlobal); Assert.NotEqual(TargetPointer.Null, continuationMT); - TypeHandle handle = rts.GetTypeHandle(continuationMT); + ITypeHandle handle = rts.GetTypeHandle(continuationMT); Assert.False(rts.IsContinuationWithoutMetadata(handle)); } @@ -58,7 +58,7 @@ public void ObjectMethodTable_IsNotContinuation(TestConfiguration config) TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle objectHandle = rts.GetTypeHandle(objectMT); + ITypeHandle objectHandle = rts.GetTypeHandle(objectMT); Assert.False(rts.IsContinuationWithoutMetadata(objectHandle)); } @@ -111,7 +111,7 @@ public void ThreadLocalContinuation_IsContinuation(TestConfiguration config) // 4. Verify the object's MethodTable is a continuation subtype via the cDAC. TargetPointer objMT = Target.Contracts.Object.GetMethodTableAddress( new TargetPointer(continuationAddress)); - TypeHandle handle = rts.GetTypeHandle(objMT); + ITypeHandle handle = rts.GetTypeHandle(objMT); Assert.True(rts.IsContinuationWithoutMetadata(handle)); } } diff --git a/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs index bfa5069716f41a..c11036738231ee 100644 --- a/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs @@ -94,10 +94,10 @@ public void CCW_InterfaceMethodTablesAreReadable(TestConfiguration config) if (iface.MethodTable == TargetPointer.Null) continue; - // Verify the MethodTable is readable by resolving it to a TypeHandle. - TypeHandle typeHandle = rts.GetTypeHandle(iface.MethodTable); + // Verify the MethodTable is readable by resolving it to a ITypeHandle. + ITypeHandle typeHandle = rts.GetTypeHandle(iface.MethodTable); Assert.False(typeHandle.IsNull, - $"Expected non-null TypeHandle for MethodTable 0x{iface.MethodTable:X} in CCW 0x{ccwPtr:X}"); + $"Expected non-null ITypeHandle for MethodTable 0x{iface.MethodTable:X} in CCW 0x{ccwPtr:X}"); Assert.True(rts.GetBaseSize(typeHandle) > 0, $"Expected positive base size for MethodTable 0x{iface.MethodTable:X} in CCW 0x{ccwPtr:X}"); } diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs index ee1e39bf5e03eb..83f0996a2d50ef 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs @@ -74,7 +74,7 @@ private unsafe void AssertRoundTrip(DacDbiImpl dbi, ulong objAddr) IRuntimeTypeSystem rts = Target.Contracts.RuntimeTypeSystem; TargetPointer expectedMT = Target.Contracts.Object.GetMethodTableAddress(new TargetPointer(objAddr)); - TypeHandle expectedTh = rts.GetTypeHandle(expectedMT); + ITypeHandle expectedTh = rts.GetTypeHandle(expectedMT); DebuggerIPCE_ExpandedTypeData expanded; int hr = dbi.GetObjectExpandedTypeInfo(AreValueTypesBoxed.NoValueTypeBoxing, objAddr, &expanded); @@ -99,7 +99,7 @@ private unsafe void AssertRoundTrip(DacDbiImpl dbi, ulong objAddr) } } - private static DebuggerIPCE_BasicTypeData[] BuildArgInfoList(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHandle typeHandle) + private static DebuggerIPCE_BasicTypeData[] BuildArgInfoList(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle typeHandle) { if (rts.IsArray(typeHandle, out _)) { @@ -108,7 +108,7 @@ private static DebuggerIPCE_BasicTypeData[] BuildArgInfoList(DacDbiImpl dbi, IRu return one; } - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length == 0) return Array.Empty(); diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs index 5f4313d4d1d8f2..1dfce0799bb9e4 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs @@ -141,7 +141,7 @@ public unsafe void GetTypeHandle_ReturnsMethodTableForTypeDef(TestConfiguration // Get the well-known System.Object MethodTable TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle objectHandle = rts.GetTypeHandle(objectMT); + ITypeHandle objectHandle = rts.GetTypeHandle(objectMT); // Get its TypeDef token and module pointer uint token = rts.GetTypeDefToken(objectHandle); diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs index 03f529402b927e..6145d1b2aaf0b3 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs @@ -57,7 +57,7 @@ public unsafe void GetTypeLayout_Object_CrossValidatesContract(TestConfiguration DacDbiImpl dbi = CreateDacDbi(); TargetPointer objectMT = Target.ReadPointer(Target.ReadGlobalPointer("ObjectMethodTable")); - TypeHandle objectHandle = Target.Contracts.RuntimeTypeSystem.GetTypeHandle(objectMT); + ITypeHandle objectHandle = Target.Contracts.RuntimeTypeSystem.GetTypeHandle(objectMT); COR_TYPE_LAYOUT layout; int hr = dbi.GetTypeLayout(objectMT.Value, &layout); @@ -79,8 +79,8 @@ public unsafe void GetArrayLayout_ObjectArray_CrossValidatesContract(TestConfigu IRuntimeTypeSystem rts = Target.Contracts.RuntimeTypeSystem; TargetPointer arrayMT = Target.ReadPointer(Target.ReadGlobalPointer("ObjectArrayMethodTable")); - TypeHandle arrayHandle = rts.GetTypeHandle(arrayMT); - TypeHandle componentHandle = rts.GetTypeParam(arrayHandle); + ITypeHandle arrayHandle = rts.GetTypeHandle(arrayMT); + ITypeHandle componentHandle = rts.GetTypeParam(arrayHandle); Assert.True(rts.IsArray(arrayHandle, out uint rank)); COR_ARRAY_LAYOUT layout; @@ -213,7 +213,7 @@ public unsafe void GetObjectFields_NullLayout_QueriesIntroducedFieldCount(TestCo IRuntimeTypeSystem rts = Target.Contracts.RuntimeTypeSystem; TargetPointer stringMT = Target.ReadPointer(Target.ReadGlobalPointer("StringMethodTable")); - TypeHandle stringHandle = rts.GetTypeHandle(stringMT); + ITypeHandle stringHandle = rts.GetTypeHandle(stringMT); uint expectedCount = GetIntroducedInstanceFieldCount(rts, stringHandle); uint fetched = 0; @@ -231,7 +231,7 @@ public unsafe void GetObjectFields_String_CrossValidatesContract(TestConfigurati IRuntimeTypeSystem rts = Target.Contracts.RuntimeTypeSystem; TargetPointer stringMT = Target.ReadPointer(Target.ReadGlobalPointer("StringMethodTable")); - TypeHandle stringHandle = rts.GetTypeHandle(stringMT); + ITypeHandle stringHandle = rts.GetTypeHandle(stringMT); uint cFields = GetIntroducedInstanceFieldCount(rts, stringHandle); Assert.True(cFields >= 1, $"Expected System.String to have at least one introduced instance field, got {cFields}"); @@ -262,13 +262,13 @@ public unsafe void GetObjectFields_String_CrossValidatesContract(TestConfigurati } } - private static uint GetIntroducedInstanceFieldCount(IRuntimeTypeSystem rts, TypeHandle handle) + private static uint GetIntroducedInstanceFieldCount(IRuntimeTypeSystem rts, ITypeHandle handle) { uint count = rts.GetNumInstanceFields(handle); TargetPointer parentMT = rts.GetParentMethodTable(handle); if (parentMT != TargetPointer.Null) { - TypeHandle parentHandle = rts.GetTypeHandle(parentMT); + ITypeHandle parentHandle = rts.GetTypeHandle(parentMT); count -= rts.GetNumInstanceFields(parentHandle); } return count; diff --git a/src/native/managed/cdac/tests/DumpTests/IXCLRDataMethodDefinitionDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/IXCLRDataMethodDefinitionDumpTests.cs index d352cb87f19c8a..236bb3ecde4b04 100644 --- a/src/native/managed/cdac/tests/DumpTests/IXCLRDataMethodDefinitionDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/IXCLRDataMethodDefinitionDumpTests.cs @@ -233,7 +233,7 @@ private IXCLRDataMethodDefinition GetGenericMethodDefinition() TargetPointer systemAssembly = loader.GetSystemAssembly(); Contracts.ModuleHandle coreLibModule = loader.GetModuleHandleFromAssemblyPtr(systemAssembly); - TypeHandle listTypeDef = Target.Contracts.ManagedTypeSource.GetTypeHandle( + ITypeHandle listTypeDef = Target.Contracts.ManagedTypeSource.GetTypeHandle( "System.Collections.Generic.List`1"); Assert.True(listTypeDef.Address != 0, "Could not find List<> type definition in CoreLib"); diff --git a/src/native/managed/cdac/tests/DumpTests/IXCLRDataValueDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/IXCLRDataValueDumpTests.cs index ae75899ea40618..1ca092dd50e103 100644 --- a/src/native/managed/cdac/tests/DumpTests/IXCLRDataValueDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/IXCLRDataValueDumpTests.cs @@ -242,7 +242,7 @@ public void GetFlags_ReturnsExpectedFlags(TestConfiguration config) // --- GenericInst and ByRef --- // GenericInstAndByRefVars(List listArg, KeyValuePair kvpArg, ref int refArg) - // Native DAC passes ByRef TypeHandle directly to GetTypeFieldValueFlags which + // Native DAC passes ByRef ITypeHandle directly to GetTypeFieldValueFlags which // returns DEFAULT (ELEMENT_TYPE_BYREF is not IsObjRef, not primitive, etc.). var genericInstArgs = GetArgumentValues("GenericInstAndByRefVars"); AssertEach(genericInstArgs, new Dictionary> diff --git a/src/native/managed/cdac/tests/DumpTests/ObjectiveCMarshalDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/ObjectiveCMarshalDumpTests.cs index e237b3bb344ebc..b5aefff43f0fb3 100644 --- a/src/native/managed/cdac/tests/DumpTests/ObjectiveCMarshalDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/ObjectiveCMarshalDumpTests.cs @@ -40,7 +40,7 @@ private List FindTrackedObjects() if (mt == TargetPointer.Null) continue; - TypeHandle typeHandle = rtsContract.GetTypeHandle(mt); + ITypeHandle typeHandle = rtsContract.GetTypeHandle(mt); if (rtsContract.IsTrackedReferenceWithFinalizer(typeHandle)) results.Add(objectAddress); } diff --git a/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs index 9960f1b6469eea..f01c9da1a06d08 100644 --- a/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs @@ -48,7 +48,7 @@ public void RuntimeTypeSystem_ObjectMethodTableIsValid(TestConfiguration config) TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); Assert.NotEqual(TargetPointer.Null, objectMT); - TypeHandle handle = rts.GetTypeHandle(objectMT); + ITypeHandle handle = rts.GetTypeHandle(objectMT); Assert.False(rts.IsFreeObjectMethodTable(handle)); Assert.True(rts.IsObject(handle)); } @@ -65,7 +65,7 @@ public void RuntimeTypeSystem_FreeObjectMethodTableIsValid(TestConfiguration con TargetPointer freeObjMT = Target.ReadPointer(freeObjMTGlobal); Assert.NotEqual(TargetPointer.Null, freeObjMT); - TypeHandle handle = rts.GetTypeHandle(freeObjMT); + ITypeHandle handle = rts.GetTypeHandle(freeObjMT); Assert.True(rts.IsFreeObjectMethodTable(handle)); Assert.False(rts.IsObject(handle)); } @@ -82,7 +82,7 @@ public void RuntimeTypeSystem_StringMethodTableIsString(TestConfiguration config TargetPointer stringMT = Target.ReadPointer(stringMTGlobal); Assert.NotEqual(TargetPointer.Null, stringMT); - TypeHandle handle = rts.GetTypeHandle(stringMT); + ITypeHandle handle = rts.GetTypeHandle(stringMT); Assert.True(rts.IsString(handle)); Assert.False(rts.IsObject(handle)); } @@ -96,7 +96,7 @@ public void RuntimeTypeSystem_ObjectMethodTableHasParent(TestConfiguration confi TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle objectHandle = rts.GetTypeHandle(objectMT); + ITypeHandle objectHandle = rts.GetTypeHandle(objectMT); // System.Object has no parent TargetPointer parent = rts.GetParentMethodTable(objectHandle); @@ -115,7 +115,7 @@ public void RuntimeTypeSystem_StringHasObjectParent(TestConfiguration config) TargetPointer stringMTGlobal = Target.ReadGlobalPointer("StringMethodTable"); TargetPointer stringMT = Target.ReadPointer(stringMTGlobal); - TypeHandle stringHandle = rts.GetTypeHandle(stringMT); + ITypeHandle stringHandle = rts.GetTypeHandle(stringMT); // System.String's parent should be System.Object TargetPointer parent = rts.GetParentMethodTable(stringHandle); @@ -131,7 +131,7 @@ public void RuntimeTypeSystem_ObjectMethodTableHasReasonableBaseSize(TestConfigu TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle handle = rts.GetTypeHandle(objectMT); + ITypeHandle handle = rts.GetTypeHandle(objectMT); uint baseSize = rts.GetBaseSize(handle); Assert.True(baseSize > 0 && baseSize < 1024, @@ -147,7 +147,7 @@ public void RuntimeTypeSystem_StringHasNonZeroComponentSize(TestConfiguration co TargetPointer stringMTGlobal = Target.ReadGlobalPointer("StringMethodTable"); TargetPointer stringMT = Target.ReadPointer(stringMTGlobal); - TypeHandle handle = rts.GetTypeHandle(stringMT); + ITypeHandle handle = rts.GetTypeHandle(stringMT); // String has a component size (char size = 2) uint componentSize = rts.GetComponentSize(handle); @@ -163,7 +163,7 @@ public void RuntimeTypeSystem_ObjectMethodTableContainsNoGCPointers(TestConfigur TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle handle = rts.GetTypeHandle(objectMT); + ITypeHandle handle = rts.GetTypeHandle(objectMT); // System.Object has no GC-tracked fields Assert.False(rts.ContainsGCPointers(handle)); @@ -178,7 +178,7 @@ public void RuntimeTypeSystem_ObjectMethodTableHasValidToken(TestConfiguration c TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle handle = rts.GetTypeHandle(objectMT); + ITypeHandle handle = rts.GetTypeHandle(objectMT); uint token = rts.GetTypeDefToken(handle); // TypeDef tokens have the form 0x02xxxxxx @@ -194,7 +194,7 @@ public void RuntimeTypeSystem_ObjectMethodTableHasMethods(TestConfiguration conf TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle handle = rts.GetTypeHandle(objectMT); + ITypeHandle handle = rts.GetTypeHandle(objectMT); ushort numMethods = rts.GetNumMethods(handle); // System.Object has ToString, Equals, GetHashCode, Finalize, etc. @@ -210,7 +210,7 @@ public void RuntimeTypeSystem_StringIsNotGenericTypeDefinition(TestConfiguration TargetPointer stringMTGlobal = Target.ReadGlobalPointer("StringMethodTable"); TargetPointer stringMT = Target.ReadPointer(stringMTGlobal); - TypeHandle handle = rts.GetTypeHandle(stringMT); + ITypeHandle handle = rts.GetTypeHandle(stringMT); Assert.False(rts.IsGenericTypeDefinition(handle)); } @@ -224,7 +224,7 @@ public void RuntimeTypeSystem_StringCorElementTypeIsClass(TestConfiguration conf TargetPointer stringMTGlobal = Target.ReadGlobalPointer("StringMethodTable"); TargetPointer stringMT = Target.ReadPointer(stringMTGlobal); - TypeHandle handle = rts.GetTypeHandle(stringMT); + ITypeHandle handle = rts.GetTypeHandle(stringMT); // GetSignatureCorElementType returns the MethodTable's stored CorElementType, // which is Class for System.String (not CorElementType.String) @@ -243,11 +243,11 @@ public void RuntimeTypeSystem_IsCorElementTypeObjRef_AreConsistent(TestConfigura TargetPointer stringMT = Target.ReadPointer(Target.ReadGlobalPointer("StringMethodTable")); TargetPointer objectArrayMT = Target.ReadPointer(Target.ReadGlobalPointer("ObjectArrayMethodTable")); - TypeHandle objectHandle = rts.GetTypeHandle(objectMT); - TypeHandle stringHandle = rts.GetTypeHandle(stringMT); - TypeHandle objectArrayHandle = rts.GetTypeHandle(objectArrayMT); + ITypeHandle objectHandle = rts.GetTypeHandle(objectMT); + ITypeHandle stringHandle = rts.GetTypeHandle(stringMT); + ITypeHandle objectArrayHandle = rts.GetTypeHandle(objectArrayMT); - TypeHandle intPtrHandle = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.IntPtr"); + ITypeHandle intPtrHandle = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.IntPtr"); Assert.True(rts.IsCorElementTypeObjRef(rts.GetInternalCorElementType(objectHandle))); Assert.True(rts.IsCorElementTypeObjRef(rts.GetInternalCorElementType(stringHandle))); @@ -264,7 +264,7 @@ public void RuntimeTypeSystem_ObjectMethodTableHasIntroducedMethods(TestConfigur TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle handle = rts.GetTypeHandle(objectMT); + ITypeHandle handle = rts.GetTypeHandle(objectMT); IEnumerable methodDescs = rts.GetIntroducedMethodDescs(handle); List methods = methodDescs.ToList(); @@ -291,7 +291,7 @@ public void RuntimeTypeSystem_ObjectMethodTableHasLoadedModule(TestConfiguration TargetPointer objectMTGlobal = Target.ReadGlobalPointer("ObjectMethodTable"); TargetPointer objectMT = Target.ReadPointer(objectMTGlobal); - TypeHandle handle = rts.GetTypeHandle(objectMT); + ITypeHandle handle = rts.GetTypeHandle(objectMT); TargetPointer modulePointer = rts.GetModule(handle); Assert.NotEqual(TargetPointer.Null, modulePointer); @@ -311,7 +311,7 @@ public void RuntimeTypeSystem_StringMethodTableHasLoadedModule(TestConfiguration TargetPointer stringMTGlobal = Target.ReadGlobalPointer("StringMethodTable"); TargetPointer stringMT = Target.ReadPointer(stringMTGlobal); - TypeHandle handle = rts.GetTypeHandle(stringMT); + ITypeHandle handle = rts.GetTypeHandle(stringMT); TargetPointer modulePointer = rts.GetModule(handle); Assert.NotEqual(TargetPointer.Null, modulePointer); @@ -333,7 +333,7 @@ public void RuntimeTypeSystem_ConcreteTypesDoNotContainGenericVariables(TestConf { TargetPointer mtGlobal = Target.ReadGlobalPointer(globalName); TargetPointer mt = Target.ReadPointer(mtGlobal); - TypeHandle handle = rts.GetTypeHandle(mt); + ITypeHandle handle = rts.GetTypeHandle(mt); Assert.False(rts.ContainsGenericVariables(handle), $"{globalName} should not contain generic variables"); } @@ -356,12 +356,12 @@ public void RuntimeTypeSystem_IsValueType(TestConfiguration config) Assert.False(rts.IsValueType(rts.GetTypeHandle(stringMT))); // Int32 is a value type (TruePrimitive category) - TypeHandle int32Type = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.Int32"); + ITypeHandle int32Type = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.Int32"); Assert.True(int32Type.Address != 0, "Could not find Int32 type in CoreLib"); Assert.True(rts.IsValueType(int32Type)); // Nullable<> is a value type (Category_Nullable) — loaded because Container.Value is int? - TypeHandle nullableType = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.Nullable`1"); + ITypeHandle nullableType = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.Nullable`1"); Assert.True(nullableType.Address != 0, "Could not find Nullable<> type in CoreLib"); Assert.True(rts.IsValueType(nullableType)); } @@ -376,7 +376,7 @@ public void RuntimeTypeSystem_GenericTypeDefinitionContainsGenericVariables(Test // Look up the generic type definition List<> in System.Private.CoreLib. // The debuggee instantiates List, so the runtime has loaded // both the closed List MT and the open List type definition MT. - TypeHandle listTypeDef = Target.Contracts.ManagedTypeSource.GetTypeHandle( + ITypeHandle listTypeDef = Target.Contracts.ManagedTypeSource.GetTypeHandle( "System.Collections.Generic.List`1"); Assert.True(listTypeDef.Address != 0, "Could not find List<> type definition in CoreLib"); diff --git a/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs b/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs index 0758ea776d196a..d1e9320cce6cfc 100644 --- a/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs @@ -115,7 +115,7 @@ public static void AddMethodDesc(this Mock mock, CodeVersion public static void AddMethodTable(this Mock mock, MockCodeVersions builder, CodeVersionsMockMethodTable methodTable) { - TypeHandle handle = new TypeHandle(methodTable.Address); + ITypeHandle handle = new ITypeHandle(methodTable.Address); mock.Setup(r => r.GetTypeHandle(methodTable.Address)).Returns(address => { // this is not quite accurate on 32 bit architectures, but it's good enough for testing diff --git a/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs b/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs index 1f91dd724dc280..6b9b0ab9fe03fc 100644 --- a/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs @@ -339,8 +339,8 @@ public void IsExceptionObject(MockTarget.Architecture arch, int inheritanceDepth mockRts.Setup(r => r.GetWellKnownMethodTable(WellKnownMethodTable.Exception)).Returns(exceptionMT); if (intermediateMTs.Length == 0 && !isException) { - mockRts.Setup(r => r.GetTypeHandle(objectMT)).Returns(new TypeHandle(objectMT)); - mockRts.Setup(r => r.GetParentMethodTable(new TypeHandle(objectMT))).Returns(TargetPointer.Null); + mockRts.Setup(r => r.GetTypeHandle(objectMT)).Returns(new ITypeHandle(objectMT)); + mockRts.Setup(r => r.GetParentMethodTable(new ITypeHandle(objectMT))).Returns(TargetPointer.Null); } for (int i = 0; i < intermediateMTs.Length; i++) { @@ -349,8 +349,8 @@ public void IsExceptionObject(MockTarget.Architecture arch, int inheritanceDepth ? intermediateMTs[i + 1] : isException ? exceptionMT : TargetPointer.Null; - mockRts.Setup(r => r.GetTypeHandle(current)).Returns(new TypeHandle(current)); - mockRts.Setup(r => r.GetParentMethodTable(new TypeHandle(current))).Returns(parent); + mockRts.Setup(r => r.GetTypeHandle(current)).Returns(new ITypeHandle(current)); + mockRts.Setup(r => r.GetParentMethodTable(new ITypeHandle(current))).Returns(parent); } var (dacDbi, _) = CreateDacDbiWithExceptionMT(arch, mockObject, mockRts); diff --git a/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs b/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs index 3f4e527eb91fee..bece4fcd63501b 100644 --- a/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs @@ -199,14 +199,14 @@ private static IException CreateContract(MockTarget.Architecture arch, StackTrac Name = "CombinedPtrArray", }); - TypeHandle combinedHandle = new(CombinedArrayMTAddr); + ITypeHandle combinedHandle = new(CombinedArrayMTAddr); objectMock.Setup(o => o.GetMethodTableAddress(CombinedArrayAddr)).Returns(CombinedArrayMTAddr); rtsMock.Setup(r => r.GetTypeHandle(CombinedArrayMTAddr)).Returns(combinedHandle); rtsMock.Setup(r => r.ContainsGCPointers(combinedHandle)).Returns(true); } else { - TypeHandle i1Handle = new(StackTraceMTAddr); + ITypeHandle i1Handle = new(StackTraceMTAddr); objectMock.Setup(o => o.GetMethodTableAddress(StackTraceObjectAddr)).Returns(StackTraceMTAddr); rtsMock.Setup(r => r.GetTypeHandle(StackTraceMTAddr)).Returns(i1Handle); rtsMock.Setup(r => r.ContainsGCPointers(i1Handle)).Returns(false); diff --git a/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs b/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs index 3eab3dd5c4914e..a8a61d0a8d1a63 100644 --- a/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs @@ -395,7 +395,7 @@ public void IsGenericMethodDefinition(MockTarget.Architecture arch) MethodDescHandle handle = rts.GetMethodDescHandle(genericMethodDef); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(rts.IsGenericMethodDefinition(handle)); - ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); + ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); Assert.Equal(0, instantiation.Length); } @@ -403,7 +403,7 @@ public void IsGenericMethodDefinition(MockTarget.Architecture arch) MethodDescHandle handle = rts.GetMethodDescHandle(genericWithInst); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(rts.IsGenericMethodDefinition(handle)); - ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); + ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); Assert.Equal(typeArgsRawAddrs.Length, instantiation.Length); for (int i = 0; i < typeArgsRawAddrs.Length; i++) { diff --git a/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs b/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs index b73c7b95175e8e..22da592b6b455a 100644 --- a/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs @@ -83,7 +83,7 @@ public void HasRuntimeTypeSystemContract(MockTarget.Architecture arch) builder => freeObjectMethodTableAddress = builder.FreeObjectMethodTableAddress); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle handle = contract.GetTypeHandle(freeObjectMethodTableAddress); + Contracts.ITypeHandle handle = contract.GetTypeHandle(freeObjectMethodTableAddress); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(contract.IsFreeObjectMethodTable(handle)); Assert.False(contract.IsObject(handle)); @@ -99,7 +99,7 @@ public void ValidateSystemObjectMethodTable(MockTarget.Architecture arch) rtsBuilder => systemObjectMethodTablePtr = rtsBuilder.SystemObjectMethodTable.Address); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle systemObjectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); + Contracts.ITypeHandle systemObjectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); Assert.Equal(systemObjectMethodTablePtr.Value, systemObjectTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(systemObjectTypeHandle)); Assert.True(contract.IsObject(systemObjectTypeHandle)); @@ -139,7 +139,7 @@ public void ValidateSystemStringMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle systemStringTypeHandle = contract.GetTypeHandle(systemStringMethodTablePtr); + Contracts.ITypeHandle systemStringTypeHandle = contract.GetTypeHandle(systemStringMethodTablePtr); Assert.Equal(systemStringMethodTablePtr.Value, systemStringTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(systemStringTypeHandle)); Assert.True(contract.IsString(systemStringTypeHandle)); @@ -249,7 +249,7 @@ public void ValidateGenericInstMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle genericInstanceTypeHandle = contract.GetTypeHandle(genericInstanceMethodTablePtr); + Contracts.ITypeHandle genericInstanceTypeHandle = contract.GetTypeHandle(genericInstanceMethodTablePtr); Assert.Equal(genericInstanceMethodTablePtr.Value, genericInstanceTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(genericInstanceTypeHandle)); Assert.False(contract.IsString(genericInstanceTypeHandle)); @@ -305,7 +305,7 @@ public void ValidateArrayInstMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle arrayInstanceTypeHandle = contract.GetTypeHandle(arrayInstanceMethodTablePtr); + Contracts.ITypeHandle arrayInstanceTypeHandle = contract.GetTypeHandle(arrayInstanceMethodTablePtr); Assert.Equal(arrayInstanceMethodTablePtr.Value, arrayInstanceTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(arrayInstanceTypeHandle)); Assert.False(contract.IsString(arrayInstanceTypeHandle)); @@ -368,7 +368,7 @@ public void IsContinuationWithoutMetadata_ReturnsTrueForContinuationType(MockTar }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + Contracts.ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.True(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); Assert.False(contract.IsFreeObjectMethodTable(continuationTypeHandle)); Assert.False(contract.IsString(continuationTypeHandle)); @@ -467,11 +467,11 @@ public void ValidateMultidimArrayRank(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle rank4Handle = contract.GetTypeHandle(rank4MethodTablePtr); + Contracts.ITypeHandle rank4Handle = contract.GetTypeHandle(rank4MethodTablePtr); Assert.True(contract.IsArray(rank4Handle, out uint rank4)); Assert.Equal(4u, rank4); - Contracts.TypeHandle rank1Handle = contract.GetTypeHandle(rank1MultiDimMethodTablePtr); + Contracts.ITypeHandle rank1Handle = contract.GetTypeHandle(rank1MultiDimMethodTablePtr); Assert.True(contract.IsArray(rank1Handle, out uint rank1)); Assert.Equal(1u, rank1); } @@ -501,10 +501,10 @@ public void IsContinuationWithoutMetadata_ReturnsFalseWhenGlobalIsNull(MockTarge }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); + Contracts.ITypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(objectTypeHandle)); - Contracts.TypeHandle childTypeHandle = contract.GetTypeHandle(childMethodTablePtr); + Contracts.ITypeHandle childTypeHandle = contract.GetTypeHandle(childMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(childTypeHandle)); } @@ -538,7 +538,7 @@ public void ValidateContinuationMethodTablePointer(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + Contracts.ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.Equal(continuationInstanceMethodTablePtr.Value, continuationTypeHandle.Address.Value); Assert.True(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); } @@ -566,7 +566,7 @@ public void IsContinuationWithoutMetadata_ReturnsTrueForSingletonEEClass(MockTar }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - TypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.True(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); } @@ -594,7 +594,7 @@ public void IsContinuationWithoutMetadata_ReturnsFalseForOwnEEClass(MockTarget.A }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - TypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); } @@ -608,7 +608,7 @@ public void IsContinuationWithoutMetadata_ReturnsFalseForRegularType(MockTarget. rtsBuilder => systemObjectMethodTablePtr = rtsBuilder.SystemObjectMethodTable.Address); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - TypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); + ITypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(objectTypeHandle)); } @@ -647,10 +647,10 @@ public void IsCanonicalMethodTable_ReturnsTrueForCanonicalAndFalseForNonCanonica IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - TypeHandle canonTh = contract.GetTypeHandle(canonicalMethodTablePtr); + ITypeHandle canonTh = contract.GetTypeHandle(canonicalMethodTablePtr); Assert.True(contract.IsCanonicalMethodTable(canonTh)); - TypeHandle nonCanonTh = contract.GetTypeHandle(nonCanonicalMethodTablePtr); + ITypeHandle nonCanonTh = contract.GetTypeHandle(nonCanonicalMethodTablePtr); Assert.False(contract.IsCanonicalMethodTable(nonCanonTh)); } @@ -846,7 +846,7 @@ public void RequiresAlign8(MockTarget.Architecture arch, bool flagSet) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(methodTablePtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(methodTablePtr); Assert.Equal(flagSet, contract.RequiresAlign8(typeHandle)); } @@ -865,7 +865,7 @@ public void GetGCDescSeriesReturnsEmptyForNonMethodTable(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeDescHandle = contract.GetTypeHandle(typeDescAddress); + Contracts.ITypeHandle typeDescHandle = contract.GetTypeHandle(typeDescAddress); Assert.Empty(contract.GetGCDescSeries(typeDescHandle)); } @@ -891,7 +891,7 @@ public void GetGCDescSeriesReturnsEmptyWhenNoGCPointers(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.False(contract.ContainsGCPointers(typeHandle)); Assert.Empty(contract.GetGCDescSeries(typeHandle)); } @@ -938,7 +938,7 @@ public void GetGCDescSeriesReturnsSingleSeries(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle).ToArray(); @@ -993,7 +993,7 @@ public void GetGCDescSeriesReturnsMultipleSeriesInOrder(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle).ToArray(); Assert.Equal(expectedSeries.Length, series.Length); @@ -1049,7 +1049,7 @@ public void GetGCDescSeriesReturnsSingleValueClassSeries(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); // Pass numComponents=1 because value-class GCDesc iterates one element per component. @@ -1108,7 +1108,7 @@ public void GetGCDescSeriesReturnsMultipleValueClassSeries(MockTarget.Architectu }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); // Pass numComponents=1 because value-class GCDesc iterates one element per component. (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle, 1).ToArray(); @@ -1169,7 +1169,7 @@ public void GetGCDescSeriesRegularSeriesWithArrayNumComponents(MockTarget.Archit }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); uint pointerSz = (uint)target.PointerSize; @@ -1227,7 +1227,7 @@ public void GetGCDescSeriesValueClassRepeatingWithArrayNumComponents(MockTarget. }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); uint elemSize = 2 * (uint)target.PointerSize; uint startOff = 3u * (uint)target.PointerSize; diff --git a/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs b/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs index aec9e6e73763d1..b7a54248fa60e5 100644 --- a/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs @@ -295,7 +295,7 @@ public void GetObjectClassName_UnloadedModule(MockTarget.Architecture arch) }, builder => { var mockRts = new Mock(); - TypeHandle handle = new TypeHandle(TestMethodTableAddress); + ITypeHandle handle = new ITypeHandle(TestMethodTableAddress); mockRts.Setup(r => r.GetTypeHandle(TestMethodTableAddress)).Returns(handle); mockRts.Setup(r => r.GetModule(handle)).Returns(TargetPointer.Null); @@ -343,7 +343,7 @@ public void GetObjectClassName_NullBufferReturnsNeededSize(MockTarget.Architectu }, builder => { var mockRts = new Mock(); - TypeHandle handle = new TypeHandle(TestMethodTableAddress); + ITypeHandle handle = new ITypeHandle(TestMethodTableAddress); mockRts.Setup(r => r.GetTypeHandle(TestMethodTableAddress)).Returns(handle); mockRts.Setup(r => r.GetModule(handle)).Returns(TargetPointer.Null); diff --git a/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs b/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs index 5134255237294d..aa77f85df9c7a2 100644 --- a/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs @@ -45,8 +45,8 @@ private static (Mock Rts, Mock Loader) CreateMocks( ModuleFlags flags) { var rts = new Mock(); - rts.Setup(r => r.GetTypeHandle(mtPtr)).Returns(new TypeHandle(mtPtr)); - rts.Setup(r => r.GetModule(It.Is(th => th.Address == mtPtr))).Returns(modulePtr); + rts.Setup(r => r.GetTypeHandle(mtPtr)).Returns(new ITypeHandle(mtPtr)); + rts.Setup(r => r.GetModule(It.Is(th => th.Address == mtPtr))).Returns(modulePtr); var loader = new Mock(); Contracts.ModuleHandle moduleHandle = new Contracts.ModuleHandle(modulePtr); @@ -72,7 +72,7 @@ public void TypeDescHandle_ReturnsEmpty(MockTarget.Architecture arch) IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; Assert.NotNull(contract); - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(tdPtr); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(tdPtr); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: false)); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: true)); } @@ -92,7 +92,7 @@ public void EnCNotEnabled_ReturnsEmpty(MockTarget.Architecture arch) TestPlaceholderTarget target = CreateTarget(arch, builder, rts, loader); IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: false)); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: true)); } @@ -112,7 +112,7 @@ public void NoMatchingClassData_ReturnsEmpty(MockTarget.Architecture arch) TestPlaceholderTarget target = CreateTarget(arch, builder, rts, loader); IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(otherMt); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(otherMt); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: false)); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: true)); } @@ -129,7 +129,7 @@ public void EmptyClassList_ReturnsEmpty(MockTarget.Architecture arch) TestPlaceholderTarget target = CreateTarget(arch, builder, rts, loader); IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: false)); Assert.Empty(contract.EnumerateAddedFieldDescs(th, staticFields: true)); } @@ -149,7 +149,7 @@ public void InstanceFields_ReturnedInOrder(MockTarget.Architecture arch) TestPlaceholderTarget target = CreateTarget(arch, builder, rts, loader); IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); // FieldDesc is the address of the FieldDesc subfield within each element. ulong fieldDescOffset = (ulong)builder.AddedFieldElementLayout.GetField("FieldDesc").Offset; @@ -174,7 +174,7 @@ public void StaticFields_ReturnedInOrder(MockTarget.Architecture arch) TestPlaceholderTarget target = CreateTarget(arch, builder, rts, loader); IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); ulong fieldDescOffset = (ulong)builder.AddedFieldElementLayout.GetField("FieldDesc").Offset; ulong[] expected = staticElems.Select(e => e.Address + fieldDescOffset).ToArray(); @@ -199,7 +199,7 @@ public void InstanceAndStaticFields_ReturnedSeparately(MockTarget.Architecture a TestPlaceholderTarget target = CreateTarget(arch, builder, rts, loader); IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); ulong fieldDescOffset = (ulong)builder.AddedFieldElementLayout.GetField("FieldDesc").Offset; Assert.Equal( @@ -227,7 +227,7 @@ public void SecondEntryMatches(MockTarget.Architecture arch) TestPlaceholderTarget target = CreateTarget(arch, builder, rts, loader); IRuntimeMutableTypeSystem contract = target.Contracts.RuntimeMutableTypeSystem; - TypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); + ITypeHandle th = target.Contracts.RuntimeTypeSystem.GetTypeHandle(mtPtr); ulong fieldDescOffset = (ulong)builder.AddedFieldElementLayout.GetField("FieldDesc").Offset; ulong[] expected = instanceElems.Select(e => e.Address + fieldDescOffset).ToArray(); diff --git a/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs b/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs index 1da74f6d4d2a19..46fb1d9aa0d0b5 100644 --- a/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs +++ b/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs @@ -40,7 +40,7 @@ private static ISOSDacInterface5 CreateDac5( ILCodeVersionHandle ilCodeVersion = ILCodeVersionHandle.CreateSynthetic(s_moduleAddr, 0x06000001); MethodDescHandle methodDescHandle = new MethodDescHandle(s_methodDescAddr); - TypeHandle typeHandle = new TypeHandle(s_methodTableAddr); + ITypeHandle typeHandle = new ITypeHandle(s_methodTableAddr); Contracts.ModuleHandle moduleHandle = new Contracts.ModuleHandle(s_moduleAddr); mockCodeVersions diff --git a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs index a93d3d9263a34c..537f77e93fc480 100644 --- a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs @@ -47,21 +47,21 @@ public void GetModule(MockTarget.Architecture arch) { // Type var type IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); TargetPointer actualModule = rts.GetModule(handle); Assert.Equal(module, actualModule); } { // Param type - pointing at var type IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); TargetPointer actualModule = rts.GetModule(handle); Assert.Equal(module, actualModule); } { // Function pointer - always null IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); TargetPointer actualModule = rts.GetModule(handle); Assert.Equal(TargetPointer.Null, actualModule); } @@ -98,24 +98,24 @@ public void GetTypeParam(MockTarget.Architecture arch) { IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); bool res = rts.HasTypeParam(handle); Assert.True(res); - TypeHandle typeParam = rts.GetTypeParam(handle); + ITypeHandle typeParam = rts.GetTypeParam(handle); Assert.Equal(typePointerHandle, typeParam.Address); Assert.Equal(typePointerRawAddr, typeParam.TypeDescAddress()); } { // Function pointer IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); bool res = rts.HasTypeParam(handle); Assert.False(res); } { // Type var type IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); bool res = rts.HasTypeParam(handle); Assert.False(res); } @@ -160,8 +160,8 @@ public void IsFunctionPointer(MockTarget.Architecture arch) { // Function pointer IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); - bool res = rts.IsFunctionPointer(handle, out ReadOnlySpan actualRetAndArgTypes, out SignatureCallingConvention actualCallConv); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); + bool res = rts.IsFunctionPointer(handle, out ReadOnlySpan actualRetAndArgTypes, out SignatureCallingConvention actualCallConv); Assert.True(res); Assert.Equal(callConv, (byte)actualCallConv); Assert.Equal(retAndArgTypesHandle.Length, actualRetAndArgTypes.Length); @@ -174,14 +174,14 @@ public void IsFunctionPointer(MockTarget.Architecture arch) { // Param type IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); bool res = rts.IsFunctionPointer(handle, out _, out _); Assert.False(res); } { // Type var type IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); bool res = rts.IsFunctionPointer(handle, out _, out _); Assert.False(res); } @@ -227,7 +227,7 @@ public void IsGenericVariable(MockTarget.Architecture arch) { // Var IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(varType)); bool res = rts.IsGenericVariable(handle, out TargetPointer actualModule, out uint actualToken); Assert.True(res); Assert.Equal(module, actualModule); @@ -236,7 +236,7 @@ public void IsGenericVariable(MockTarget.Architecture arch) { // MVar IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(mvarType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(mvarType)); bool res = rts.IsGenericVariable(handle, out TargetPointer actualModule, out uint actualToken); Assert.True(res); Assert.Equal(module, actualModule); @@ -245,14 +245,14 @@ public void IsGenericVariable(MockTarget.Architecture arch) { // Function pointer IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); bool res = rts.IsGenericVariable(handle, out _, out _); Assert.False(res); } { // Param type IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; - TypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); + ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(paramType)); bool res = rts.IsGenericVariable(handle, out _, out _); Assert.False(res); } From 9fa927220252b95eaa9a261ef6ea9b5fc9f1e0ad Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Wed, 24 Jun 2026 10:09:53 -0400 Subject: [PATCH 02/23] [cdac] Extract ITypeHandle interface with NullTypeHandle and TargetTypeHandle Convert ITypeHandle from a readonly struct to an interface, enabling polymorphic type handles. Add NullTypeHandle (Abstractions) and TargetTypeHandle (Contracts) implementations. Replace ReadOnlySpan with ITypeHandle[] in public API signatures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Contracts/IRuntimeTypeSystem.cs | 40 ++++++---- .../CallingConvention/ArgumentLocation.cs | 6 +- .../CallingConvention/CallingConvention_1.cs | 62 +++++++-------- .../CallingConvention/CdacTypeHandle.cs | 23 +++--- .../Contracts/ManagedTypeSource_1.cs | 10 ++- .../TypeHandleImplementations.cs | 28 +++++++ .../Contracts/RuntimeTypeSystem_1.cs | 79 ++++++++++--------- .../Signature/SignatureTypeProvider.cs | 6 +- .../Contracts/StackWalk/GC/GcScanContext.cs | 2 +- .../StackWalk/GC/GcSignatureTypeProvider.cs | 4 +- .../ClrDataFrame.cs | 4 +- .../ClrDataMethodDefinition.cs | 4 +- .../Dbi/DacDbiImpl.cs | 26 +++--- .../Dbi/IDacDbiInterface.cs | 2 +- .../Dbi/TypeDataWalk.cs | 64 +++++++-------- .../SOSDacImpl.IXCLRDataProcess.cs | 4 +- .../SigFormat.cs | 17 ++-- .../TypeNameBuilder.cs | 37 ++++----- .../CollectibleGenericInstDumpTests.cs | 10 +-- .../DacDbi/DacDbiApproxTypeHandleDumpTests.cs | 50 ++++++------ .../DacDbi/DacDbiExactTypeHandleDumpTests.cs | 3 +- .../Debuggees/CrossModule/Lib/Types.cs | 2 +- .../cdac/tests/UnitTests/CodeVersionsTests.cs | 2 +- .../cdac/tests/UnitTests/DacDbiImplTests.cs | 8 +- .../cdac/tests/UnitTests/ExceptionTests.cs | 4 +- .../cdac/tests/UnitTests/MethodDescTests.cs | 4 +- .../cdac/tests/UnitTests/ObjectTests.cs | 4 +- .../RuntimeMutableTypeSystemTests.cs | 2 +- .../tests/UnitTests/SOSDacInterface5Tests.cs | 2 +- .../cdac/tests/UnitTests/TypeDescTests.cs | 3 +- 30 files changed, 282 insertions(+), 230 deletions(-) create mode 100644 src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index 36a3952dcb7771..da7b0722e85d28 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -8,18 +8,30 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; -// an opaque handle to a type handle. See IMetadata.GetMethodTableData -public readonly struct ITypeHandle +/// +/// An opaque handle to a runtime type, backed by a target-process MethodTable or +/// TypeDesc address. +/// +public interface ITypeHandle : IEquatable { - // TODO-Layering: These members should be accessible only to contract implementations. - public ITypeHandle(TargetPointer address) - { - Address = address; - } - - public TargetPointer Address { get; } + TargetPointer Address { get; } + bool IsNull { get; } + static ITypeHandle Null { get; } = NullTypeHandle.Instance; +} - public bool IsNull => Address == 0; +/// +/// Singleton ITypeHandle representing the absence of a type. Exposed only through +/// ; the concrete type is an implementation detail. +/// +internal sealed class NullTypeHandle : ITypeHandle +{ + public static readonly NullTypeHandle Instance = new(); + private NullTypeHandle() { } + public TargetPointer Address => TargetPointer.Null; + public bool IsNull => true; + public bool Equals(ITypeHandle? other) => other is not null && other.IsNull; + public override bool Equals(object? obj) => obj is ITypeHandle th && Equals(th); + public override int GetHashCode() => 0; } public enum CorElementType @@ -70,7 +82,7 @@ public MethodDescHandle(TargetPointer address) public TargetPointer Address { get; } } -public readonly record struct TypedByRefInfo(TargetPointer Data, TargetPointer ITypeHandle); +public readonly record struct TypedByRefInfo(TargetPointer Data, TargetPointer TypeHandle); public enum ArrayFunctionType { @@ -220,7 +232,7 @@ public interface IRuntimeTypeSystem : IContract TargetPointer GetNonGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) => throw new NotImplementedException(); - ReadOnlySpan GetInstantiation(ITypeHandle typeHandle) => throw new NotImplementedException(); + ImmutableArray GetInstantiation(ITypeHandle typeHandle) => throw new NotImplementedException(); public bool IsClassInited(ITypeHandle typeHandle) => throw new NotImplementedException(); public bool IsInitError(ITypeHandle typeHandle) => throw new NotImplementedException(); bool IsGenericTypeDefinition(ITypeHandle typeHandle) => throw new NotImplementedException(); @@ -252,7 +264,7 @@ public interface IRuntimeTypeSystem : IContract ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default) => throw new NotImplementedException(); ITypeHandle GetPrimitiveType(CorElementType typeCode) => throw new NotImplementedException(); bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token) => throw new NotImplementedException(); - bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) => throw new NotImplementedException(); + bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv) => throw new NotImplementedException(); bool IsPointer(ITypeHandle typeHandle) => throw new NotImplementedException(); bool IsTypeDesc(ITypeHandle typeHandle) => throw new NotImplementedException(); TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) => throw new NotImplementedException(); @@ -265,7 +277,7 @@ public interface IRuntimeTypeSystem : IContract // Return true for an uninstantiated generic method bool IsGenericMethodDefinition(MethodDescHandle methodDesc) => throw new NotImplementedException(); - ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDesc) => throw new NotImplementedException(); + ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDesc) => throw new NotImplementedException(); GenericContextLoc GetGenericContextLoc(MethodDescHandle methodDescHandle) => throw new NotImplementedException(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs index c00ac4284a9ec9..25f3f962cdfe83 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs @@ -9,7 +9,7 @@ internal readonly struct ArgumentLocation { public int Offset { get; init; } public CorElementType ElementType { get; init; } - public TypeHandle TypeHandle { get; init; } + public ITypeHandle TypeHandle { get; init; } public bool IsThis { get; init; } public bool IsValueTypeThis { get; init; } public bool IsParamType { get; init; } @@ -27,10 +27,10 @@ internal readonly struct ArgumentLocation // pointer slot. public bool IsByRefLikeStruct { get; init; } - // For generic-instantiation parameters with an uncached closed TypeHandle, + // For generic-instantiation parameters with an uncached closed ITypeHandle, // the open generic MethodTable (e.g. Span for a Span arg) so // encoders can inspect type structure as a fallback. - public TypeHandle OpenGenericType { get; init; } + public ITypeHandle OpenGenericType { get; init; } // SystemV-AMD64 struct passed in registers. Offset is the StructInRegsOffset // sentinel; the encoder consumes SysVEightByteDescriptor + SysVIdxGenReg. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs index e2598a756e4d31..8c2a3c6c78c9ae 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs @@ -58,7 +58,7 @@ private readonly record struct ArgumentLayout( // Per-parameter metadata captured at signature-decode time. We track this // out-of-band because the standard SignatureTypeProvider collapses // ELEMENT_TYPE_BYREF, _PTR, _SZARRAY, and _ARRAY into the underlying type - // (or a null TypeHandle when the runtime hasn't cached the constructed + // (or a null ITypeHandle when the runtime hasn't cached the constructed // form), making the top-level element type unrecoverable from // methodSig.ParameterTypes alone. private readonly struct ParamTypeInfo @@ -69,14 +69,14 @@ private readonly struct ParamTypeInfo // Outermost element type of the parameter signature, if known // (Byref / Ptr / SzArray / Array). The enum's zero value (default) // means "no constructed-type wrapper -- caller should fall back to - // GetSignatureCorElementType on the underlying TypeHandle". + // GetSignatureCorElementType on the underlying ITypeHandle". public CdacCorElementType OutermostKind { get; init; } // For generic-instantiation parameters, the open generic type // (e.g. Span for a Span arg). Used by the encoder when the - // constructed TypeHandle is null (uncached) to fall back to + // constructed ITypeHandle is null (uncached) to fall back to // attributes of the open type (IsByRefLike, etc.). - public TypeHandle OpenGenericType { get; init; } + public ITypeHandle OpenGenericType { get; init; } } private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) @@ -84,13 +84,13 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; IRuntimeInfo runtimeInfo = _target.Contracts.RuntimeInfo; - MethodSignature methodSig = DecodeMethodSignature(rts, methodDesc); + MethodSignature methodSig = DecodeMethodSignature(rts, methodDesc); // Re-decode the same signature with a wrapper provider to learn each // parameter's outermost element type (Byref / Ptr / SzArray / Array) // and whether it's wrapped in ELEMENT_TYPE_BYREF. The standard // SignatureTypeProvider hides these wrappers (returning a null - // TypeHandle when GetConstructedType isn't cached), so without this + // ITypeHandle when GetConstructedType isn't cached), so without this // out-of-band metadata the encoder would silently drop any arg whose // outermost wrapper isn't in the loader's available-type-params list. ParamTypeInfo[] paramInfo = DecodeParamTypeInfo(rts, methodDesc, methodSig.ParameterTypes.Length); @@ -148,7 +148,7 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) if (hasThis) { TargetPointer methodTablePtr = rts.GetMethodTable(methodDesc); - TypeHandle owningType = rts.GetTypeHandle(methodTablePtr); + ITypeHandle owningType = rts.GetTypeHandle(methodTablePtr); bool isValueTypeThis = rts.IsValueType(owningType) && !rts.IsUnboxingStub(methodDesc); arguments.Add(new ArgumentLocation @@ -250,13 +250,13 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) // token per managed-pointer field inside the unboxed struct // via ByRefPointerOffsetsReporter, in addition to any REF // tokens from GCDesc. For constructed generic instantiations - // (Span) the closed TypeHandle may be uncached/null, so + // (Span) the closed ITypeHandle may be uncached/null, so // we fall back to the open generic type captured during // signature decoding. bool isByRefLikeStruct = false; if (elemType == CdacCorElementType.ValueType && !passedByRef) { - TypeHandle probe = methodSig.ParameterTypes[argIndex]; + ITypeHandle probe = methodSig.ParameterTypes[argIndex]; if (probe.Address == TargetPointer.Null) probe = paramInfo[argIndex].OpenGenericType; if (probe.Address != TargetPointer.Null) @@ -287,11 +287,11 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) return new ArgumentLayout(arguments, cbStackPop); } - private MethodSignature DecodeMethodSignature( + private MethodSignature DecodeMethodSignature( IRuntimeTypeSystem rts, MethodDescHandle methodDesc) { TargetPointer methodTablePtr = rts.GetMethodTable(methodDesc); - TypeHandle typeHandle = rts.GetTypeHandle(methodTablePtr); + ITypeHandle typeHandle = rts.GetTypeHandle(methodTablePtr); TargetPointer modulePtr = rts.GetModule(typeHandle); ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); @@ -305,7 +305,7 @@ private MethodSignature DecodeMethodSignature( // NotSupportedException for whichever side it wasn't parameterized on. MethodSigContext context = new(methodDesc, typeHandle); MethodAndTypeContextProvider provider = new(_target, moduleHandle, rts); - RuntimeSignatureDecoder decoder = new( + RuntimeSignatureDecoder decoder = new( provider, _target, mdReader, context); if (!rts.TryGetMethodSignature(methodDesc, out ReadOnlySpan methodSig)) @@ -333,7 +333,7 @@ private ParamTypeInfo[] DecodeParamTypeInfo(IRuntimeTypeSystem rts, MethodDescHa return Array.Empty(); TargetPointer methodTablePtr = rts.GetMethodTable(methodDesc); - TypeHandle typeHandle = rts.GetTypeHandle(methodTablePtr); + ITypeHandle typeHandle = rts.GetTypeHandle(methodTablePtr); TargetPointer modulePtr = rts.GetModule(typeHandle); ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); @@ -414,13 +414,13 @@ private CdacTypeHandle GetIntPtrTypeHandle(IRuntimeTypeSystem rts) } // Result type produced by ParamMetadataProvider. Carries the underlying - // TypeHandle (resolved by the inner provider when possible) plus the + // ITypeHandle (resolved by the inner provider when possible) plus the // outermost element type and an IsByRef flag, both of which the standard // SignatureTypeProvider would otherwise drop on the floor when the runtime // hasn't cached the constructed-type instantiation. private readonly struct TrackedType { - public TypeHandle Underlying { get; init; } + public ITypeHandle Underlying { get; init; } public bool IsByRef { get; init; } // The outermost ELEMENT_TYPE_* wrapper applied to this signature. // The enum's zero value (default) means "no constructed-type wrapper; @@ -429,14 +429,14 @@ private readonly struct TrackedType // For generic instantiations: the open generic type before // GetConstructedType collapsed it. Lets the encoder inspect // attributes (IsByRefLike, etc.) even when the constructed - // TypeHandle isn't cached. - public TypeHandle OpenGeneric { get; init; } + // ITypeHandle isn't cached. + public ITypeHandle OpenGeneric { get; init; } } // ISignatureTypeProvider wrapper that records the outermost // ELEMENT_TYPE_* wrapper (BYREF / PTR / SZARRAY / ARRAY) on each parameter // so the caller can recover that information even when the standard - // SignatureTypeProvider would have returned a null TypeHandle from + // SignatureTypeProvider would have returned a null ITypeHandle from // GetConstructedType. Used only by DecodeParamTypeInfo. The generic // context is a MethodDescHandle so both ELEMENT_TYPE_VAR and _MVAR can be // resolved by the inner MethodGenericContextProvider. @@ -456,7 +456,7 @@ public ParamMetadataProvider(MethodAndTypeContextProvider inner, IRuntimeTypeSys // know to fall back to GetSignatureCorElementType on Underlying. The // constructed-type overrides (ByRef/Ptr/SzArray/Array) set // OutermostKind explicitly. - private static TrackedType Wrap(TypeHandle th) + private static TrackedType Wrap(ITypeHandle th) => new() { Underlying = th }; public TrackedType GetByReferenceType(TrackedType elementType) @@ -480,10 +480,10 @@ public TrackedType GetFunctionPointerType(MethodSignature signature public TrackedType GetGenericInstantiation(TrackedType genericType, ImmutableArray typeArguments) { - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(typeArguments.Length); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(typeArguments.Length); for (int i = 0; i < typeArguments.Length; i++) builder.Add(typeArguments[i].Underlying); - TypeHandle constructed = _inner.GetGenericInstantiation(genericType.Underlying, builder.ToImmutable()); + ITypeHandle constructed = _inner.GetGenericInstantiation(genericType.Underlying, builder.ToImmutable()); // GetConstructedType returns null when the runtime hasn't cached // this exact instantiation. Recover the would-be top-level kind @@ -539,15 +539,15 @@ public TrackedType GetInternalModifiedType(TargetPointer typeHandlePointer, Trac // ELEMENT_TYPE_VAR resolution). The existing SignatureTypeProvider // only resolves one or the other depending on T -- since a method // signature can reference both kinds of type parameters, we need both. - internal readonly record struct MethodSigContext(MethodDescHandle Method, TypeHandle OwningType); + internal readonly record struct MethodSigContext(MethodDescHandle Method, ITypeHandle OwningType); // SignatureTypeProvider variant that resolves both VAR (owning type's // type parameters) and MVAR (method's type parameters) by pulling the // appropriate field out of the MethodSigContext. Overrides the base // implementations, which only handle one direction. // Specialization that resolves generic parameters via the - // MethodSigContext (open generic MD + owning TypeHandle) instead of - // requiring the context to be exactly a MethodDescHandle or TypeHandle. + // MethodSigContext (open generic MD + owning ITypeHandle) instead of + // requiring the context to be exactly a MethodDescHandle or ITypeHandle. // // The base SignatureTypeProvider deliberately keeps its // GetGenericMethodParameter / GetGenericTypeParameter non-virtual to @@ -563,7 +563,7 @@ public TrackedType GetInternalModifiedType(TargetPointer typeHandlePointer, Trac // methods without making the base virtual. internal sealed class MethodAndTypeContextProvider : SignatureTypeProvider, - IRuntimeSignatureTypeProvider + IRuntimeSignatureTypeProvider { private readonly IRuntimeTypeSystem _rts; @@ -573,10 +573,10 @@ public MethodAndTypeContextProvider(Target target, ModuleHandle moduleHandle, IR _rts = rts; } - public new TypeHandle GetGenericMethodParameter(MethodSigContext context, int index) + public new ITypeHandle GetGenericMethodParameter(MethodSigContext context, int index) => _rts.GetGenericMethodInstantiation(context.Method)[index]; - public new TypeHandle GetGenericTypeParameter(MethodSigContext context, int index) + public new ITypeHandle GetGenericTypeParameter(MethodSigContext context, int index) => _rts.GetInstantiation(context.OwningType)[index]; } @@ -702,7 +702,7 @@ public MethodAndTypeContextProvider(Target target, ModuleHandle moduleHandle, IR // The byref/ptr distinction is preserved at the // FieldDesc level regardless of which T closes // the type. - TypeHandle probe = arg.TypeHandle; + ITypeHandle probe = arg.TypeHandle; if (probe.Address == TargetPointer.Null) probe = arg.OpenGenericType; if (probe.Address != TargetPointer.Null) @@ -851,7 +851,7 @@ private static GenericContextLoc SafeGetGenericContextLoc(IRuntimeTypeSystem rts // handle wrappers. private static void EmitByRefLikeInterior( IRuntimeTypeSystem rts, - TypeHandle byRefLikeType, + ITypeHandle byRefLikeType, int baseOffset, SortedDictionary tokens) { @@ -861,7 +861,7 @@ private static void EmitByRefLikeInterior( private static void EmitByRefLikeInteriorRecursive( IRuntimeTypeSystem rts, - TypeHandle byRefLikeType, + ITypeHandle byRefLikeType, int baseOffset, SortedDictionary tokens, int depth) @@ -910,7 +910,7 @@ private static void EmitByRefLikeInteriorRecursive( // Nested value-type field. Recurse only if the field's own // MethodTable is ByRefLike (matches runtime Find(FieldDesc*) // in ByRefPointerOffsetsReporter). - TypeHandle nested = rts.GetFieldDescApproxTypeHandle(fdPtr); + ITypeHandle nested = rts.GetFieldDescApproxTypeHandle(fdPtr); if (nested.Address == TargetPointer.Null) continue; bool nestedByRefLike; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs index 542b461c2efeef..bad1d3bc8aa79b 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs @@ -6,36 +6,37 @@ using Internal.CallingConvention; using Internal.JitInterface; +using CdacITypeHandle = Microsoft.Diagnostics.DataContractReader.Contracts.ITypeHandle; using CdacCorElementType = Microsoft.Diagnostics.DataContractReader.Contracts.CorElementType; using SharedCorElementType = Internal.CorConstants.CorElementType; namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; /// -/// Adapts cDAC's IRuntimeTypeSystem + TypeHandle to the shared +/// Adapts cDAC's IRuntimeTypeSystem + ITypeHandle to the shared /// interface used by ArgIterator for calling-convention computation. /// -internal readonly struct CdacTypeHandle : ITypeHandle +internal readonly struct CdacTypeHandle : Internal.CallingConvention.ITypeHandle { - private readonly TypeHandle _typeHandle; + private readonly CdacITypeHandle _typeHandle; private readonly Target _target; // Outermost ELEMENT_TYPE_* wrapper (PTR / BYREF / SZARRAY / ARRAY / etc.) // recorded out-of-band by the signature wrapper provider in // CallingConvention_1.ParamMetadataProvider. Used when the underlying - // TypeHandle would be null (the runtime hasn't cached the constructed + // ITypeHandle would be null (the runtime hasn't cached the constructed // form), in which case Rts.GetSignatureCorElementType would return 0 and // ArgIterator would fail to classify the arg for stack-size accounting. // `default` (the enum's 0 value, which CorElementType doesn't name) means // "no override; ask Rts". private readonly CdacCorElementType _kindOverride; - public CdacTypeHandle(TypeHandle typeHandle, Target target) + public CdacTypeHandle(CdacITypeHandle typeHandle, Target target) : this(typeHandle, target, kindOverride: default) { } - public CdacTypeHandle(TypeHandle typeHandle, Target target, CdacCorElementType kindOverride) + public CdacTypeHandle(CdacITypeHandle typeHandle, Target target, CdacCorElementType kindOverride) { _typeHandle = typeHandle; _target = target; @@ -62,7 +63,7 @@ public int GetSize() // Constructed pointer/array/byref args always occupy one TADDR slot // in the transition block (the actual pointee is reached via the // pointer value, not stored inline). When _kindOverride is set, the - // underlying TypeHandle may be null (uncached PTR), so GetBaseSize + // underlying ITypeHandle may be null (uncached PTR), so GetBaseSize // would fault. if (_kindOverride is CdacCorElementType.Ptr or CdacCorElementType.Byref @@ -92,7 +93,7 @@ public SharedCorElementType GetCorElementType() return (SharedCorElementType)0; // Mirror the runtime's MetaSig::PeekArgNormalized -- for value types - // it resolves the closed TypeHandle and returns + // it resolves the closed ITypeHandle and returns // MethodTable::GetInternalCorElementType, which collapses enums to // their underlying primitive (byte enum -> U1, int enum -> I4, ...). // The shared ArgIterator's x86 IsArgumentInRegister relies on this @@ -184,7 +185,7 @@ public bool IsTrivialPointerSizedStruct() // Walk instance fields: exactly one, and that field must itself be a // pointer-sized primitive (IntPtr/UIntPtr/I/U/Ptr/FnPtr) or another // trivial pointer-sized struct. Mirrors crossgen2's - // TypeHandle.IsTrivialPointerSizedStruct (ILCompiler.ReadyToRun). + // ITypeHandle.IsTrivialPointerSizedStruct (ILCompiler.ReadyToRun). TargetPointer? singleFieldType = null; foreach (TargetPointer fieldDesc in Rts.GetFieldDescList(_typeHandle)) { @@ -216,9 +217,9 @@ public bool IsTrivialPointerSizedStruct() case CdacCorElementType.ValueType: // Recurse: if the wrapped struct is itself a trivial // pointer-sized struct, we are too. Resolve the field's - // TypeHandle via the field's metadata signature and + // ITypeHandle via the field's metadata signature and // re-run IsTrivialPointerSizedStruct on it. - TypeHandle nested = Rts.GetFieldDescApproxTypeHandle(singleFieldType.Value); + CdacITypeHandle nested = Rts.GetFieldDescApproxTypeHandle(singleFieldType.Value); if (nested.IsNull) return false; return new CdacTypeHandle(nested, _target).IsTrivialPointerSizedStruct(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs index fabb056bfecac2..6a4ccba7b41763 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs @@ -91,12 +91,16 @@ public ITypeHandle GetTypeHandle(string fullyQualifiedName) public bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle) { - if (_typeHandleCache.TryGetValue(fullyQualifiedName, out typeHandle)) + if (_typeHandleCache.TryGetValue(fullyQualifiedName, out var cached)) + { + typeHandle = cached; return !typeHandle.IsNull; + } if (!TryResolveType(fullyQualifiedName, out typeHandle, out _, out _)) { - _typeHandleCache[fullyQualifiedName] = new ITypeHandle(TargetPointer.Null); + typeHandle = ITypeHandle.Null; + _typeHandleCache[fullyQualifiedName] = ITypeHandle.Null; return false; } @@ -248,7 +252,7 @@ private bool TryBuildTypeInfo(string managedFqName, out Target.TypeInfo info) private bool TryResolveType(string managedFqName, out ITypeHandle th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef) { - th = new ITypeHandle(TargetPointer.Null); + th = ITypeHandle.Null; typeDef = default; ILoader loader = _target.Contracts.Loader; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs new file mode 100644 index 00000000000000..65b84c55b8b06b --- /dev/null +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Diagnostics.DataContractReader.Contracts; + +/// +/// An ITypeHandle backed by a real target-process address (MethodTable* or TypeDesc*). +/// +public sealed class TargetTypeHandle : ITypeHandle, IEquatable +{ + public TargetTypeHandle(TargetPointer address) + { + Address = address; + } + + public TargetPointer Address { get; } + public bool IsNull => Address == 0; + + public bool Equals(ITypeHandle? other) + => other is TargetTypeHandle t && Address == t.Address; + public bool Equals(TargetTypeHandle? other) + => other is not null && Address == other.Address; + public override bool Equals(object? obj) + => obj is ITypeHandle th && Equals(th); + public override int GetHashCode() => Address.GetHashCode(); +} diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index b8e2e369bdbc0d..d76a3b0c5edd74 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -75,13 +75,13 @@ internal MethodTable(Data.MethodTable data) { public TypeKey(ITypeHandle typeHandle, CorElementType elementType, int rank, ImmutableArray typeArgs, SignatureCallingConvention callConv = SignatureCallingConvention.Default) { - ITypeHandle = typeHandle; + TypeHandle = typeHandle; ElementType = elementType; Rank = rank; TypeArgs = typeArgs; CallConv = callConv; } - public ITypeHandle ITypeHandle { get; } + public ITypeHandle TypeHandle { get; } public CorElementType ElementType { get; } public int Rank { get; } public ImmutableArray TypeArgs { get; } @@ -89,7 +89,7 @@ public TypeKey(ITypeHandle typeHandle, CorElementType elementType, int rank, Imm public bool Equals(TypeKey other) { - if (ElementType != other.ElementType || Rank != other.Rank || CallConv != other.CallConv || TypeArgs.Length != other.TypeArgs.Length || !ITypeHandle.Equals(other.ITypeHandle)) + if (ElementType != other.ElementType || Rank != other.Rank || CallConv != other.CallConv || TypeArgs.Length != other.TypeArgs.Length || !TypeHandle.Equals(other.TypeHandle)) return false; for (int i = 0; i < TypeArgs.Length; i++) { @@ -103,7 +103,7 @@ public bool Equals(TypeKey other) public override int GetHashCode() { - int hash = HashCode.Combine(ITypeHandle.GetHashCode(), (int)ElementType, Rank, (int)CallConv); + int hash = HashCode.Combine(TypeHandle.GetHashCode(), (int)ElementType, Rank, (int)CallConv); foreach (ITypeHandle th in TypeArgs) { hash = HashCode.Combine(hash, th.GetHashCode()); @@ -353,15 +353,16 @@ private InstantiatedMethodDesc(Target target, TargetPointer methodDescPointer) TargetPointer perInstInfo = _desc.PerInstInfo; if ((perInstInfo == TargetPointer.Null) || (numGenericArgs == 0)) { - Instantiation = System.Array.Empty(); + Instantiation = ImmutableArray.Empty; } else { - Instantiation = new ITypeHandle[numGenericArgs]; + var builder = ImmutableArray.CreateBuilder(numGenericArgs); for (int i = 0; i < numGenericArgs; i++) { - Instantiation[i] = rts.GetTypeHandle(target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)i)); + builder.Add(rts.GetTypeHandle(target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)i))); } + Instantiation = builder.MoveToImmutable(); } } @@ -370,7 +371,7 @@ private InstantiatedMethodDesc(Target target, TargetPointer methodDescPointer) internal bool IsGenericMethodDefinition => HasFlags(InstantiatedMethodDescFlags2.KindMask, InstantiatedMethodDescFlags2.GenericMethodDefinition); internal bool HasPerInstInfo => _desc.PerInstInfo != TargetPointer.Null; internal bool HasMethodInstantiation => IsGenericMethodDefinition || HasPerInstInfo; - public ITypeHandle[] Instantiation { get; } + public ImmutableArray Instantiation { get; } } private sealed class DynamicMethodDesc : IData @@ -476,14 +477,14 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) // if we already validated this address, return a handle if (_methodTables.ContainsKey(typeHandlePointer)) { - return new ITypeHandle(typeHandlePointer); + return new TargetTypeHandle(typeHandlePointer); } // Check for a TypeDesc if (addressLowBits == TypeHandleBits.TypeDesc) { // This is a TypeDesc - return new ITypeHandle(typeHandlePointer); + return new TargetTypeHandle(typeHandlePointer); } TargetPointer methodTablePointer = typeHandlePointer; @@ -494,7 +495,7 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) // we already cached the data, we must have validated the address, create the representation struct for our use MethodTable trustedMethodTable = new MethodTable(methodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTable); - return new ITypeHandle(methodTablePointer); + return new TargetTypeHandle(methodTablePointer); } // If it's the free object method table, we trust it to be valid @@ -503,7 +504,7 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) Data.MethodTable freeObjectMethodTableData = _target.ProcessedData.GetOrAdd(methodTablePointer); MethodTable trustedMethodTable = new MethodTable(freeObjectMethodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTable); - return new ITypeHandle(methodTablePointer); + return new TargetTypeHandle(methodTablePointer); } // Otherwse, get ready to validate @@ -515,7 +516,7 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) Data.MethodTable trustedMethodTableData = _target.ProcessedData.GetOrAdd(methodTablePointer); MethodTable trustedMethodTableF = new MethodTable(trustedMethodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTableF); - return new ITypeHandle(methodTablePointer); + return new TargetTypeHandle(methodTablePointer); } public TargetPointer GetModule(ITypeHandle typeHandle) { @@ -773,7 +774,7 @@ private int GetVectorHFAElementSize(ITypeHandle typeHandle) if (elemSize == 0) return 0; - ReadOnlySpan instantiation = ((IRuntimeTypeSystem)this).GetInstantiation(typeHandle); + ImmutableArray instantiation = ((IRuntimeTypeSystem)this).GetInstantiation(typeHandle); if (instantiation.Length < 1) return 0; @@ -986,14 +987,14 @@ public TargetPointer GetNonGCStaticsBasePointer(ITypeHandle typeHandle) return dynamicStaticsInfo.NonGCStatics; } - public ReadOnlySpan GetInstantiation(ITypeHandle typeHandle) + public ImmutableArray GetInstantiation(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) - return default; + return ImmutableArray.Empty; MethodTable methodTable = _methodTables[typeHandle.Address]; if (!methodTable.Flags.HasInstantiation) - return default; + return ImmutableArray.Empty; return _target.ProcessedData.GetOrAdd(typeHandle.Address).TypeHandles; } @@ -1020,7 +1021,7 @@ private sealed class TypeInstantiation : IData { public static TypeInstantiation Create(Target target, TargetPointer address) => new TypeInstantiation(target, address); - public ITypeHandle[] TypeHandles { get; } + public ImmutableArray TypeHandles { get; } private TypeInstantiation(Target target, TargetPointer typePointer) { RuntimeTypeSystem_1 rts = (RuntimeTypeSystem_1)target.Contracts.RuntimeTypeSystem; @@ -1036,11 +1037,12 @@ private TypeInstantiation(Target target, TargetPointer typePointer) TargetPointer dictionaryPointer = target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)(genericsDictInfo.NumDicts - 1)); int numberOfGenericArgs = genericsDictInfo.NumTypeArgs; - TypeHandles = new ITypeHandle[numberOfGenericArgs]; + var builder = ImmutableArray.CreateBuilder(numberOfGenericArgs); for (int i = 0; i < numberOfGenericArgs; i++) { - TypeHandles[i] = rts.GetTypeHandle(target.ReadPointer(dictionaryPointer + (ulong)target.PointerSize * (ulong)i)); + builder.Add(rts.GetTypeHandle(target.ReadPointer(dictionaryPointer + (ulong)target.PointerSize * (ulong)i))); } + TypeHandles = builder.MoveToImmutable(); } } @@ -1060,7 +1062,7 @@ public bool ContainsGenericVariables(ITypeHandle typeHandle) else if (type == CorElementType.FnPtr) { - _ = IsFunctionPointer(typeHandle, out ReadOnlySpan signatureTypeArgs, out _); + _ = IsFunctionPointer(typeHandle, out ImmutableArray signatureTypeArgs, out _); foreach (ITypeHandle sigTypeArg in signatureTypeArgs) { if (ContainsGenericVariables(sigTypeArg)) @@ -1241,7 +1243,7 @@ private ITypeHandle GetRootTypeParam(ITypeHandle typeHandle) private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle potentialMatch, ImmutableArray typeArguments) { - ReadOnlySpan instantiation = GetInstantiation(potentialMatch); + ImmutableArray instantiation = GetInstantiation(potentialMatch); if (instantiation.Length != typeArguments.Length) return false; @@ -1271,7 +1273,7 @@ private bool ArrayPtrMatch(ITypeHandle elementType, CorElementType corElementTyp private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) { - if (!IsFunctionPointer(candidate, out ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) + if (!IsFunctionPointer(candidate, out ImmutableArray candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) return false; if (candidateCallConv != callConv) return false; @@ -1302,9 +1304,9 @@ private bool IsLoaded(ITypeHandle typeHandle) ITypeHandle IRuntimeTypeSystem.GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) { - if (typeHandle.Address == TargetPointer.Null && corElementType != CorElementType.FnPtr) - return new ITypeHandle(TargetPointer.Null); - if (_typeHandles.TryGetValue(new TypeKey(typeHandle, corElementType, rank, typeArguments, callConv), out ITypeHandle existing)) + if (typeHandle.IsNull && corElementType != CorElementType.FnPtr) + return ITypeHandle.Null; + if (_typeHandles.TryGetValue(new TypeKey(typeHandle, corElementType, rank, typeArguments, callConv), out ITypeHandle? existing) && existing is not null) return existing; ILoader loaderContract = _target.Contracts.Loader; TargetPointer loaderModule; @@ -1342,7 +1344,7 @@ ITypeHandle IRuntimeTypeSystem.GetConstructedType(ITypeHandle typeHandle, CorEle return potentialMatch; } } - return new ITypeHandle(TargetPointer.Null); + return ITypeHandle.Null; } // See https://github.com/dotnet/runtime/blob/e1979b72ccb5f916649f1d9949ef663254790c25/src/coreclr/vm/clsload.cpp#L78 @@ -1446,9 +1448,9 @@ public bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, return false; } - public bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) + public bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv) { - retAndArgTypes = default; + retAndArgTypes = ImmutableArray.Empty; callConv = default; if (!typeHandle.IsTypeDesc()) @@ -1513,7 +1515,7 @@ private sealed class FunctionPointerRetAndArgs : IData new FunctionPointerRetAndArgs(target, address); - public ITypeHandle[] TypeHandles { get; } + public ImmutableArray TypeHandles { get; } private FunctionPointerRetAndArgs(Target target, TargetPointer typePointer) { RuntimeTypeSystem_1 rts = (RuntimeTypeSystem_1)target.Contracts.RuntimeTypeSystem; @@ -1522,11 +1524,12 @@ private FunctionPointerRetAndArgs(Target target, TargetPointer typePointer) TargetPointer retAndArgs = fnPtrTypeDesc.RetAndArgTypes; int numberOfRetAndArgTypes = checked((int)fnPtrTypeDesc.NumArgs + 1); - TypeHandles = new ITypeHandle[numberOfRetAndArgTypes]; + var builder = ImmutableArray.CreateBuilder(numberOfRetAndArgTypes); for (int i = 0; i < numberOfRetAndArgTypes; i++) { - TypeHandles[i] = rts.GetTypeHandle(target.ReadPointer(retAndArgs + (ulong)target.PointerSize * (ulong)i)); + builder.Add(rts.GetTypeHandle(target.ReadPointer(retAndArgs + (ulong)target.PointerSize * (ulong)i))); } + TypeHandles = builder.MoveToImmutable(); } } @@ -1594,12 +1597,12 @@ public bool IsGenericMethodDefinition(MethodDescHandle methodDescHandle) return AsInstantiatedMethodDesc(methodDesc).IsGenericMethodDefinition; } - public ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) + public ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) { MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; if (methodDesc.Classification != MethodClassification.Instantiated) - return default; + return ImmutableArray.Empty; return AsInstantiatedMethodDesc(methodDesc).Instantiation; } @@ -2345,16 +2348,16 @@ ITypeHandle IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldD { TargetPointer enclosingMT = ((IRuntimeTypeSystem)this).GetMTOfEnclosingClass(fieldDescPointer); if (enclosingMT == TargetPointer.Null) - return default; + return ITypeHandle.Null; ITypeHandle enclosingType = GetTypeHandle(enclosingMT); TargetPointer modulePtr = GetModule(enclosingType); if (modulePtr == TargetPointer.Null) - return default; + return ITypeHandle.Null; ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); MetadataReader? mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle); if (mdReader is null) - return default; + return ITypeHandle.Null; uint memberDef = ((IRuntimeTypeSystem)this).GetFieldDescMemberDef(fieldDescPointer); FieldDefinitionHandle fieldDefHandle = (FieldDefinitionHandle)MetadataTokens.Handle((int)memberDef); @@ -2364,7 +2367,7 @@ ITypeHandle IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldD } catch { - return default; + return ITypeHandle.Null; } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs index 10cbdd6b498cb2..813c9466bbd3d9 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs @@ -76,7 +76,7 @@ public ITypeHandle GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHa int token = MetadataTokens.GetToken((EntityHandle)handle); TargetPointer typeDefToMethodTable = _loader.GetLookupTables(_moduleHandle).TypeDefToMethodTable; TargetPointer typeHandlePtr = _loader.GetModuleLookupMapElement(typeDefToMethodTable, (uint)token, out _); - return typeHandlePtr == TargetPointer.Null ? new ITypeHandle(TargetPointer.Null) : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); + return typeHandlePtr == TargetPointer.Null ? ITypeHandle.Null : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); } public ITypeHandle GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) @@ -84,7 +84,7 @@ public ITypeHandle GetTypeFromReference(MetadataReader reader, TypeReferenceHand int token = MetadataTokens.GetToken((EntityHandle)handle); TargetPointer typeRefToMethodTable = _loader.GetLookupTables(_moduleHandle).TypeRefToMethodTable; TargetPointer typeHandlePtr = _loader.GetModuleLookupMapElement(typeRefToMethodTable, (uint)token, out _); - return typeHandlePtr == TargetPointer.Null ? new ITypeHandle(TargetPointer.Null) : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); + return typeHandlePtr == TargetPointer.Null ? ITypeHandle.Null : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); } public ITypeHandle GetTypeFromSpecification(MetadataReader reader, T context, TypeSpecificationHandle handle, byte rawTypeKind) @@ -92,7 +92,7 @@ public ITypeHandle GetTypeFromSpecification(MetadataReader reader, T context, Ty public ITypeHandle GetInternalType(TargetPointer typeHandlePointer) => typeHandlePointer == TargetPointer.Null - ? new ITypeHandle(TargetPointer.Null) + ? ITypeHandle.Null : _runtimeTypeSystem.GetTypeHandle(typeHandlePointer); public ITypeHandle GetInternalModifiedType(TargetPointer typeHandlePointer, ITypeHandle unmodifiedType, bool isRequired) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcScanContext.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcScanContext.cs index 5d76ac3159b03e..0caaa9e54959dd 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcScanContext.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcScanContext.cs @@ -171,7 +171,7 @@ private bool TryGetObjectSize(TargetPointer objAddr, TargetPointer mt, out ulong size = 0; try { - TypeHandle handle = _rts.GetTypeHandle(mt); + ITypeHandle handle = _rts.GetTypeHandle(mt); ulong baseSize = _rts.GetBaseSize(handle); uint componentSize = _rts.GetComponentSize(handle); uint numComponentsOffset = 0; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs index 3c380e16f1ac6d..a3b28755cfef91 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs @@ -87,7 +87,7 @@ public GcTypeKind GetGenericMethodParameter(GcSignatureContext genericContext, i { try { - ReadOnlySpan instantiation = _target.Contracts.RuntimeTypeSystem.GetGenericMethodInstantiation(genericContext.MethodContext); + var instantiation = _target.Contracts.RuntimeTypeSystem.GetGenericMethodInstantiation(genericContext.MethodContext); if ((uint)index >= (uint)instantiation.Length) return GcTypeKind.Ref; return ClassifyTypeHandle(instantiation[index]); @@ -117,7 +117,7 @@ public GcTypeKind GetGenericTypeParameter(GcSignatureContext genericContext, int return ClassifyTypeHandle(rts.GetTypeParam(classCtx)); } - ReadOnlySpan instantiation = rts.GetInstantiation(classCtx); + ImmutableArray instantiation = rts.GetInstantiation(classCtx); if ((uint)index >= (uint)instantiation.Length) return GcTypeKind.Ref; return ClassifyTypeHandle(instantiation[index]); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs index d4d5db77e48e52..ebb83d632e1ea6 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs @@ -742,7 +742,7 @@ public FlagSignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHan try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(mdh); + ImmutableArray methodInst = rts.GetGenericMethodInstantiation(mdh); return ResolveGenericParam(rts, methodInst[index]); } catch (System.Exception) { return ((uint)ClrDataValueFlag.DEFAULT, -1); } @@ -755,7 +755,7 @@ public FlagSignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHan IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = rts.GetMethodTable(mdh); ITypeHandle declaringType = rts.GetTypeHandle(mtAddr); - ReadOnlySpan typeInst = rts.GetInstantiation(declaringType); + var typeInst = rts.GetInstantiation(declaringType); return ResolveGenericParam(rts, typeInst[index]); } catch (System.Exception) { return ((uint)ClrDataValueFlag.DEFAULT, -1); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs index bf5ec73d4eff2b..6fec9c49a25312 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs @@ -47,7 +47,7 @@ private static bool HasClassInstantiation(Target target, MethodDescHandle md) TargetPointer mtAddr = rts.GetMethodTable(md); ITypeHandle mt = rts.GetTypeHandle(mtAddr); - return !rts.GetInstantiation(mt).IsEmpty; + return rts.GetInstantiation(mt).Length > 0; } private static bool HasMethodInstantiation(Target target, MethodDescHandle md) @@ -56,7 +56,7 @@ private static bool HasMethodInstantiation(Target target, MethodDescHandle md) if (rts.IsGenericMethodDefinition(md)) return true; - return !rts.GetGenericMethodInstantiation(md).IsEmpty; + return rts.GetGenericMethodInstantiation(md).Length > 0; } private static bool HasClassOrMethodInstantiation(Target target, MethodDescHandle md) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs index b066896d7ee031..4f1ad05fc48b07 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs @@ -2914,7 +2914,7 @@ public int GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData* pTypeData, ArgInfoL try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - ITypeHandle th = default; + ITypeHandle th = ITypeHandle.Null; CorElementType et = (CorElementType)ReadLittleEndian(pTypeData->elementType); switch (et) { @@ -3043,7 +3043,7 @@ private ITypeHandle GetExactFnPtrTypeHandle(IRuntimeTypeSystem rts, ArgInfoList* // Non-default calling conventions are not supported. // Currently passes callConv=0 to match native DAC. - return rts.GetConstructedType(default, CorElementType.FnPtr, 0, builder.MoveToImmutable()); + return rts.GetConstructedType(ITypeHandle.Null, CorElementType.FnPtr, 0, builder.MoveToImmutable()); } public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, uint* pcGenericClassTypeParams, @@ -3127,10 +3127,10 @@ public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, ui TargetPointer specMethodMtPtr = rts.GetMethodTable(pSpecificMethod); ITypeHandle thSpecMethodMt = rts.GetTypeHandle(specMethodMtPtr); ITypeHandle thMatchingParent = GetMethodTableMatchingParentClass(rts, thSpecificClass, thSpecMethodMt); - ReadOnlySpan classInst = thMatchingParent.IsNull - ? ReadOnlySpan.Empty + ImmutableArray classInst = thMatchingParent.IsNull + ? ImmutableArray.Empty : rts.GetInstantiation(thMatchingParent); - ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(pSpecificMethod); + ImmutableArray methodInst = rts.GetGenericMethodInstantiation(pSpecificMethod); cClassParams = (uint)classInst.Length; *pcGenericClassTypeParams = cClassParams; @@ -3377,10 +3377,10 @@ internal ITypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint meta mt = loader.GetModuleLookupMapElement(lookupTables.TypeRefToMethodTable, metadataToken, out _); break; default: - return default; + return ITypeHandle.Null; } if (mt == TargetPointer.Null) - return default; + return ITypeHandle.Null; return rts.GetTypeHandle(mt); } @@ -3398,7 +3398,7 @@ public int EnumerateTypeHandleParams(ulong vmTypeHandle, IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; ITypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ImmutableArray instantiation = rts.GetInstantiation(typeHandle); DebuggerIPCE_ExpandedTypeData entry; for (int i = 0; i < instantiation.Length; i++) @@ -3716,7 +3716,7 @@ public int GetTypedByRefInfo(ulong pTypedByRef, ulong* pObjRef, DebuggerIPCE_Bas { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TypedByRefInfo info = rts.GetTypedByRefInfo(pTypedByRef); - ITypeHandle th = rts.GetTypeHandle(info.ITypeHandle); + ITypeHandle th = rts.GetTypeHandle(info.TypeHandle); FillBasicTypeInfo(rts, th, out DebuggerIPCE_BasicTypeData typeData); *pTypedByRefType = typeData; *pObjRef = info.Data.Value; @@ -3856,7 +3856,7 @@ public int GetBasicObjectInfo(ulong objectAddress, Interop.BOOL* pIsValidRef, ui *pObjTypeData = default; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; // verify the object reference is readable and has a valid MethodTable - ITypeHandle th = default; + ITypeHandle th = ITypeHandle.Null; try { TargetPointer mt = _target.Contracts.Object.GetMethodTableAddress(objectAddress); @@ -5797,7 +5797,7 @@ private static ITypeHandle GetMethodTableMatchingParentClass(IRuntimeTypeSystem prev = current.Address; current = rts.GetTypeHandle(next); } - return default; + return ITypeHandle.Null; } // Shared core implementation for TypeHandleToExpandedTypeInfo and GetObjectExpandedTypeInfo. @@ -5909,7 +5909,7 @@ private void FillClassTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, D Contracts.ILoader loader = _target.Contracts.Loader; Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ImmutableArray instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length > 0) { // Generic instantiation — set the type handle so the debugger can fetch type arguments @@ -5965,7 +5965,7 @@ internal void FillBasicTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, Contracts.ILoader loader = _target.Contracts.Loader; Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ImmutableArray instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length > 0) { WriteLittleEndian(ref typeInfo.vmTypeHandle, typeHandle.Address.Value); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs index c97ead7bc9431f..a330454eb368d6 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs @@ -709,7 +709,7 @@ public unsafe partial interface IDacDbiInterface int EnumerateInstantiationFields(ulong vmAssembly, ulong vmThExact, ulong vmThApprox, nuint* pObjectSize, delegate* unmanaged fpCallback, nint pUserData); [PreserveSig] - int ITypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, ulong vmTypeHandle, DebuggerIPCE_ExpandedTypeData* pData); + int TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, ulong vmTypeHandle, DebuggerIPCE_ExpandedTypeData* pData); [PreserveSig] int GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed, ulong addr, DebuggerIPCE_ExpandedTypeData* pTypeInfo); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs index 706073acec0a2c..410b629413e748 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs @@ -11,7 +11,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Legacy; // Port of native DacDbiInterfaceImpl::TypeDataWalk // // Walks the flattened DebuggerIPCE_TypeArgData[] tree that the right side built in -// CordbType::GatherTypeData and produces a TypeHandle for the loaded representation +// CordbType::GatherTypeData and produces a ITypeHandle for the loaded representation // (exact, or canonical when generic code-sharing collapses reference type-args to // System.__Canon and value type-args to their canonical form). // @@ -19,11 +19,11 @@ internal unsafe ref struct TypeDataWalk { private readonly Target _target; private readonly IRuntimeTypeSystem _rts; - private readonly TypeHandle _canonTh; + private readonly ITypeHandle _canonTh; private DebuggerIPCE_TypeArgData* _pCurrent; private uint _remaining; - public TypeDataWalk(Target target, IRuntimeTypeSystem rts, TypeHandle canonTh, DebuggerIPCE_TypeArgData* pData, uint nData) + public TypeDataWalk(Target target, IRuntimeTypeSystem rts, ITypeHandle canonTh, DebuggerIPCE_TypeArgData* pData, uint nData) { _target = target; _rts = rts; @@ -55,11 +55,11 @@ private void Skip() } } - public TypeHandle ReadLoadedTypeHandle() + public ITypeHandle ReadLoadedTypeHandle() { DebuggerIPCE_TypeArgData* p = ReadOne(); if (p == null) - return default; + return ITypeHandle.Null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(p->data.elementType); switch (et) @@ -89,11 +89,11 @@ public TypeHandle ReadLoadedTypeHandle() } // Read a single type argument in canonicalization-aware fashion. - private TypeHandle ReadLoadedTypeArg() + private ITypeHandle ReadLoadedTypeArg() { DebuggerIPCE_TypeArgData* p = ReadOne(); if (p == null) - return default; + return ITypeHandle.Null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(p->data.elementType); switch (et) @@ -114,59 +114,59 @@ private TypeHandle ReadLoadedTypeArg() } // Read an instantiation and ask the runtime-type-system for the loaded handle. - private TypeHandle ReadLoadedInstantiation(ulong vmAssembly, uint metadataToken, uint nTypeArgs) + private ITypeHandle ReadLoadedInstantiation(ulong vmAssembly, uint metadataToken, uint nTypeArgs) { - TypeHandle typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + ITypeHandle typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); if (typeDef.IsNull) - return default; + return ITypeHandle.Null; if (nTypeArgs == 0) return typeDef; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)nTypeArgs); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)nTypeArgs); bool allOK = true; for (uint i = 0; i < nTypeArgs; i++) { - TypeHandle th = ReadLoadedTypeArg(); + ITypeHandle th = ReadLoadedTypeArg(); allOK &= !th.IsNull; builder.Add(th); } if (!allOK) - return default; + return ITypeHandle.Null; return _rts.GetConstructedType(typeDef, CorElementType.GenericInst, 0, builder.MoveToImmutable()); } - private TypeHandle ArrayTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle ArrayTypeArg(DebuggerIPCE_TypeArgData* pInfo) { - TypeHandle elem = ReadLoadedTypeArg(); + ITypeHandle elem = ReadLoadedTypeArg(); if (elem.IsNull) - return default; + return ITypeHandle.Null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(pInfo->data.elementType); int rank = (int)DacDbiImpl.ReadLittleEndian(pInfo->data.ArrayTypeData_arrayRank); - return _rts.GetConstructedType(elem, et, rank, ImmutableArray.Empty); + return _rts.GetConstructedType(elem, et, rank, ImmutableArray.Empty); } - private TypeHandle PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData* pInfo) { - TypeHandle referent = ReadLoadedTypeArg(); + ITypeHandle referent = ReadLoadedTypeArg(); if (referent.IsNull) - return default; + return ITypeHandle.Null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(pInfo->data.elementType); - return _rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + return _rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } // A generic reference type collapses to System.__Canon // (and its type arguments are skipped); a value-type instantiation is recursively // resolved. - private TypeHandle ClassTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle ClassTypeArg(DebuggerIPCE_TypeArgData* pInfo) { ulong vmAssembly = DacDbiImpl.ReadLittleEndian(pInfo->data.ClassTypeData_vmAssembly); uint metadataToken = DacDbiImpl.ReadLittleEndian(pInfo->data.ClassTypeData_metadataToken); uint numTypeArgs = DacDbiImpl.ReadLittleEndian(pInfo->numTypeArgs); CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(pInfo->data.elementType); - TypeHandle typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + ITypeHandle typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); if ((!typeDef.IsNull && _rts.IsValueType(typeDef)) || et == CorElementType.ValueType) { @@ -180,25 +180,25 @@ private TypeHandle ClassTypeArg(DebuggerIPCE_TypeArgData* pInfo) } } - private TypeHandle FnPtrTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle FnPtrTypeArg(DebuggerIPCE_TypeArgData* pInfo) { uint numTypeArgs = DacDbiImpl.ReadLittleEndian(pInfo->numTypeArgs); - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)numTypeArgs); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)numTypeArgs); bool allOK = true; for (uint i = 0; i < numTypeArgs; i++) { - TypeHandle th = ReadLoadedTypeArg(); + ITypeHandle th = ReadLoadedTypeArg(); allOK &= !th.IsNull; builder.Add(th); } if (!allOK) - return default; + return ITypeHandle.Null; // Non-default calling conventions are not supported (matches the exact-handle path). - return _rts.GetConstructedType(default, CorElementType.FnPtr, 0, builder.MoveToImmutable()); + return _rts.GetConstructedType(ITypeHandle.Null, CorElementType.FnPtr, 0, builder.MoveToImmutable()); } - private TypeHandle ObjRefOrPrimitiveTypeArg(DebuggerIPCE_TypeArgData* pInfo, CorElementType elementType) + private ITypeHandle ObjRefOrPrimitiveTypeArg(DebuggerIPCE_TypeArgData* pInfo, CorElementType elementType) { // Skip any children: they are part of a reference-typed argument that canonicalizes to __Canon. uint numTypeArgs = DacDbiImpl.ReadLittleEndian(pInfo->numTypeArgs); @@ -210,7 +210,7 @@ private TypeHandle ObjRefOrPrimitiveTypeArg(DebuggerIPCE_TypeArgData* pInfo, Cor return _rts.GetPrimitiveType(elementType); } - private TypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) + private ITypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) { ILoader loader = _target.Contracts.Loader; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; @@ -226,10 +226,10 @@ private TypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metada mt = loader.GetModuleLookupMapElement(lookupTables.TypeRefToMethodTable, metadataToken, out _); break; default: - return default; + return ITypeHandle.Null; } if (mt == TargetPointer.Null) - return default; + return ITypeHandle.Null; return rts.GetTypeHandle(mt); } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs index 387a58ea375bc0..27f054e9dc48f2 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs @@ -426,7 +426,7 @@ private bool HasClassInstantiation(MethodDescHandle md) TargetPointer mtAddr = rts.GetMethodTable(md); ITypeHandle mt = rts.GetTypeHandle(mtAddr); - return !rts.GetInstantiation(mt).IsEmpty; + return rts.GetInstantiation(mt).Length > 0; } private bool HasMethodInstantiation(MethodDescHandle md) @@ -434,7 +434,7 @@ private bool HasMethodInstantiation(MethodDescHandle md) IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; if (rts.IsGenericMethodDefinition(md)) return true; - return !rts.GetGenericMethodInstantiation(md).IsEmpty; + return rts.GetGenericMethodInstantiation(md).Length > 0; } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs index 12e8c3d2d1e1e0..9bbde3b0e4b0dc 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Immutable; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; @@ -18,8 +19,8 @@ public static unsafe void AppendSigFormat(Target target, string? memberName, string? className, string? namespaceName, - ReadOnlySpan typeInstantiation, - ReadOnlySpan methodInstantiation, + ImmutableArray typeInstantiation, + ImmutableArray methodInstantiation, bool CStringParmsOnly) { fixed (byte* pSignature = signature) @@ -36,8 +37,8 @@ public static void AppendSigFormat(Target target, string? memberName, string? className, string? namespaceName, - ReadOnlySpan typeInstantiation, - ReadOnlySpan methodInstantiation, + ImmutableArray typeInstantiation, + ImmutableArray methodInstantiation, bool CStringParmsOnly) { SignatureHeader header = signature.ReadSignatureHeader(); @@ -95,8 +96,8 @@ public static void AppendSigFormat(Target target, private static unsafe void AddTypeString(Target target, StringBuilder stringBuilder, ref BlobReader signature, - ReadOnlySpan typeInstantiation, - ReadOnlySpan methodInstantiation, + ImmutableArray typeInstantiation, + ImmutableArray methodInstantiation, MetadataReader? metadata) { string _namespace; @@ -358,7 +359,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, ITypeHan } stringBuilder.Append(name); - ReadOnlySpan instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); + var instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); if (instantiation.Length > 0) { stringBuilder.Append('<'); @@ -414,7 +415,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, ITypeHan return; case CorElementType.FnPtr: - runtimeTypeSystem.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv); + runtimeTypeSystem.IsFunctionPointer(typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv); SignatureHeader header = new SignatureHeader((byte)callConv); AddType(target, stringBuilder, retAndArgTypes[0]); stringBuilder.Append(" ("); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs index 0b76140830d9a6..be747c57896321 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; @@ -59,15 +60,15 @@ private TypeNameBuilder(StringBuilder typeString, Target target, TypeNameFormat public static void AppendMethodInternal(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, TypeNameFormat format) { - AppendMethodImpl(target, stringBuilder, method, default, format); + AppendMethodImpl(target, stringBuilder, method, ImmutableArray.Empty, format); } - public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, ReadOnlySpan typeInstantiation, TypeNameFormat format) + public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, ImmutableArray typeInstantiation, TypeNameFormat format) { IRuntimeTypeSystem runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; ILoader loader = target.Contracts.Loader; string methodName; - ITypeHandle th = default; + ITypeHandle th = ITypeHandle.Null; bool isNoMetadataMethod = runtimeTypeSystem.IsNoMetadataMethod(method, out methodName); if (isNoMetadataMethod) @@ -129,7 +130,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, } } - ReadOnlySpan genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); + var genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); if (genericMethodInstantiation.Length > 0 && !runtimeTypeSystem.IsGenericMethodDefinition(method)) { AppendInst(target, stringBuilder, genericMethodInstantiation, format); @@ -142,15 +143,15 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, runtimeTypeSystem.GetModule(runtimeTypeSystem.GetTypeHandle(runtimeTypeSystem.GetMethodTable(method)))); MetadataReader? reader = target.Contracts.EcmaMetadata.GetMetadata(methodModule); - ReadOnlySpan typeInstantiationSigFormat = default; + var typeInstantiationSigFormat = ImmutableArray.Empty; if (!th.IsNull) { typeInstantiationSigFormat = runtimeTypeSystem.GetInstantiation(th); - if (typeInstantiationSigFormat.IsEmpty && runtimeTypeSystem.IsArray(th, out _)) + if (typeInstantiationSigFormat.Length == 0 && runtimeTypeSystem.IsArray(th, out _)) { // For arrays, fill in the instantiation with the element type handle // See MethodTable::GetArrayInstantiation for coreclr equivalent - typeInstantiationSigFormat = new[] { runtimeTypeSystem.GetTypeParam(th) }; + typeInstantiationSigFormat = ImmutableArray.Create(runtimeTypeSystem.GetTypeParam(th)); } } @@ -186,16 +187,16 @@ public static ITypeHandle GetExactOwningType(IRuntimeTypeSystem runtimeTypeSyste public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.ITypeHandle typeHandle, TypeNameFormat format) { - AppendType(target, stringBuilder, typeHandle, default, format); + AppendType(target, stringBuilder, typeHandle, ImmutableArray.Empty, format); } - public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.ITypeHandle typeHandle, ReadOnlySpan typeInstantiation, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.ITypeHandle typeHandle, ImmutableArray typeInstantiation, TypeNameFormat format) { TypeNameBuilder builder = new(stringBuilder, target, format); AppendTypeCore(ref builder, typeHandle, typeInstantiation, format); } - private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandle typeHandle, ReadOnlySpan instantiation, TypeNameFormat format) + private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandle typeHandle, ImmutableArray instantiation, TypeNameFormat format) { bool toString = format.HasFlag(TypeNameFormat.FormatNamespace) && !format.HasFlag(TypeNameFormat.FormatFullInst) && !format.HasFlag(TypeNameFormat.FormatAssembly); @@ -212,13 +213,13 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandl if (elemType != Contracts.CorElementType.ValueType) { typeSystemContract.IsArray(typeHandle, out uint rank); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), default(ReadOnlySpan), (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); AppendParamTypeQualifier(ref tnb, elemType, rank); } else { tnb.TypeString.Append("VALUETYPE"); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), Array.Empty(), format & ~TypeNameFormat.FormatAssembly); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, format & ~TypeNameFormat.FormatAssembly); } } else if (typeSystemContract.IsGenericVariable(typeHandle, out TargetPointer modulePointer, out uint genericParamToken)) @@ -241,7 +242,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandl tnb.AddName(reader.GetString(genericParam.Name)); format &= ~TypeNameFormat.FormatAssembly; } - else if (typeSystemContract.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv)) + else if (typeSystemContract.IsFunctionPointer(typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv)) { if (format.HasFlag(TypeNameFormat.FormatNamespace)) { @@ -299,7 +300,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandl if (format.HasFlag(TypeNameFormat.FormatNamespace) || format.HasFlag(TypeNameFormat.FormatAssembly)) { - ReadOnlySpan instantiationSpan = typeSystemContract.GetInstantiation(typeHandle); + ImmutableArray instantiationSpan = typeSystemContract.GetInstantiation(typeHandle); if ((instantiationSpan.Length > 0) && (!typeSystemContract.IsGenericTypeDefinition(typeHandle) || toString)) { @@ -329,13 +330,13 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandl // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s // and enclose each parameter in square brackets to disambiguate the commas // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion - private static void AppendInst(Target target, StringBuilder stringBuilder, ReadOnlySpan inst, TypeNameFormat format) + private static void AppendInst(Target target, StringBuilder stringBuilder, ImmutableArray inst, TypeNameFormat format) { TypeNameBuilder tnb = new(stringBuilder, target, format, initialStateIsName: true); AppendInst(ref tnb, inst, format); } - private static void AppendInst(ref TypeNameBuilder tnb, ReadOnlySpan inst, TypeNameFormat format) + private static void AppendInst(ref TypeNameBuilder tnb, ImmutableArray inst, TypeNameFormat format) { tnb.OpenGenericArguments(); foreach (ITypeHandle arg in inst) @@ -343,11 +344,11 @@ private static void AppendInst(ref TypeNameBuilder tnb, ReadOnlySpan.Empty, format | TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAssembly); } else { - AppendTypeCore(ref tnb, arg, default, format & (TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAngleBrackets)); + AppendTypeCore(ref tnb, arg, ImmutableArray.Empty, format & (TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAngleBrackets)); } tnb.CloseGenericArgument(); } diff --git a/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs index aaec6b81b595a2..a7073fcfddc017 100644 --- a/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs @@ -34,14 +34,14 @@ public void GetConstructedType_ResolvesGenericInstWithCollectibleTypeArgument(Te // Find the List instance rooted by the debuggee. It is the // single-argument generic instantiation whose loader module differs from its // definition module — the signature of a type argument from a collectible ALC. - TypeHandle constructed = default; + ITypeHandle constructed = ITypeHandle.Null; foreach (HandleData handle in gc.GetHandles([HandleType.Strong])) { TargetPointer objAddr = Target.ReadPointer(handle.Handle); if (objAddr == TargetPointer.Null) continue; - TypeHandle candidate = rts.GetTypeHandle(objectContract.GetMethodTableAddress(objAddr)); + ITypeHandle candidate = rts.GetTypeHandle(objectContract.GetMethodTableAddress(objAddr)); if (rts.GetInstantiation(candidate).Length == 1 && rts.GetModule(candidate) != rts.GetLoaderModule(candidate) && rts.IsCollectible(candidate)) @@ -57,16 +57,16 @@ public void GetConstructedType_ResolvesGenericInstWithCollectibleTypeArgument(Te // collectible argument's module, distinct from its (CoreLib) definition module. Assert.NotEqual(rts.GetModule(constructed), rts.GetLoaderModule(constructed)); - TypeHandle typeArgument = rts.GetInstantiation(constructed)[0]; + ITypeHandle typeArgument = rts.GetInstantiation(constructed)[0]; // The open List<> definition lives in CoreLib; look it up by name. - TypeHandle listDefinition = Target.Contracts.ManagedTypeSource.GetTypeHandle( + ITypeHandle listDefinition = Target.Contracts.ManagedTypeSource.GetTypeHandle( "System.Collections.Generic.List`1"); Assert.NotEqual(TargetPointer.Null, listDefinition.Address); // Reconstruct the instantiation. This must search the collectible argument's // loader module — searching the definition's module (CoreLib) returns null. - TypeHandle resolved = rts.GetConstructedType( + ITypeHandle resolved = rts.GetConstructedType( listDefinition, CorElementType.GenericInst, 0, diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs index 2c9d3c570f4d68..cbdcc93e613b6a 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs @@ -51,7 +51,7 @@ public unsafe void RoundTrip_AllReachableHandleObjects_MatchApproxMethodTable(Te IRuntimeTypeSystem rts = Target.Contracts.RuntimeTypeSystem; TargetPointer canonMtPtr = Target.ReadPointer(Target.ReadGlobalPointer(Constants.Globals.CanonMethodTable)); - TypeHandle canonTh = rts.GetTypeHandle(canonMtPtr); + ITypeHandle canonTh = rts.GetTypeHandle(canonMtPtr); HandleType[] handleKinds = [ @@ -81,14 +81,14 @@ public unsafe void RoundTrip_AllReachableHandleObjects_MatchApproxMethodTable(Te /// and assert the resulting vmTypeHandle equals the expected canonicalized /// MethodTable for the object's type. /// - private unsafe void AssertRoundTrip(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHandle canonTh, ulong objAddr) + private unsafe void AssertRoundTrip(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ulong objAddr) { TargetPointer expectedMT = Target.Contracts.Object.GetMethodTableAddress(new TargetPointer(objAddr)); - TypeHandle expectedTh = rts.GetTypeHandle(expectedMT); + ITypeHandle expectedTh = rts.GetTypeHandle(expectedMT); // Build the expected canonicalized handle from the exact type. Mirrors the rules // applied by TypeDataWalk on the cDAC side. - TypeHandle expectedApproxTh = ApproxTopLevel(dbi, rts, canonTh, expectedTh); + ITypeHandle expectedApproxTh = ApproxTopLevel(dbi, rts, canonTh, expectedTh); if (expectedApproxTh.IsNull) return; // If the approximation rules collapse this type to null, skip the round-trip assertion. @@ -121,7 +121,7 @@ private unsafe void AssertRoundTrip(DacDbiImpl dbi, IRuntimeTypeSystem rts, Type // anything else -> 0 // ---------------------------------------------------------------------------------------- - private static int CountTypeNodes(IRuntimeTypeSystem rts, TypeHandle th) + private static int CountTypeNodes(IRuntimeTypeSystem rts, ITypeHandle th) { CorElementType et = GetElementType(rts, th); switch (et) @@ -136,7 +136,7 @@ private static int CountTypeNodes(IRuntimeTypeSystem rts, TypeHandle th) case CorElementType.ValueType: { int total = 1; - foreach (TypeHandle arg in rts.GetInstantiation(th)) + foreach (ITypeHandle arg in rts.GetInstantiation(th)) total += CountTypeNodes(rts, arg); return total; } @@ -146,7 +146,7 @@ private static int CountTypeNodes(IRuntimeTypeSystem rts, TypeHandle th) } } - private static unsafe void FillTypeNodes(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHandle th, DebuggerIPCE_TypeArgData* nodes, ref int idx) + private static unsafe void FillTypeNodes(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle th, DebuggerIPCE_TypeArgData* nodes, ref int idx) { int self = idx++; DebuggerIPCE_TypeArgData* pSelf = &nodes[self]; @@ -170,7 +170,7 @@ private static unsafe void FillTypeNodes(DacDbiImpl dbi, IRuntimeTypeSystem rts, case CorElementType.Class: case CorElementType.ValueType: { - ReadOnlySpan inst = rts.GetInstantiation(th); + ImmutableArray inst = rts.GetInstantiation(th); uint numTypeArgs = (uint)inst.Length; pSelf->numTypeArgs = BitConverter.IsLittleEndian ? numTypeArgs : System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(numTypeArgs); for (int i = 0; i < inst.Length; i++) @@ -193,7 +193,7 @@ private static unsafe void FillTypeNodes(DacDbiImpl dbi, IRuntimeTypeSystem rts, // ApproxTypeArg. Array / Ptr / Byref preserve the outer shape; the inner type goes through // ApproxTypeArg. Anything else collapses to the primitive type for its element type // (e.g. System.Object, System.String, primitives). - private TypeHandle ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHandle canonTh, TypeHandle th) + private ITypeHandle ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) { CorElementType et = GetElementType(rts, th); switch (et) @@ -201,16 +201,16 @@ private TypeHandle ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHa case CorElementType.Array: case CorElementType.SzArray: { - TypeHandle elem = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); + ITypeHandle elem = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); rts.IsArray(th, out uint rank); - return rts.GetConstructedType(elem, et, (int)rank, ImmutableArray.Empty); + return rts.GetConstructedType(elem, et, (int)rank, ImmutableArray.Empty); } case CorElementType.Ptr: case CorElementType.Byref: { - TypeHandle referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); - return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + ITypeHandle referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } case CorElementType.Class: @@ -224,16 +224,16 @@ private TypeHandle ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHa // Arg context: Class collapses to __Canon (its children skipped); ValueType is recursively // approximated; Ptr preserves shape; obj-ref primitives (Class/Object/String/SzArray/Array) - // collapse to __Canon; primitives map to their primitive TypeHandle. - private TypeHandle ApproxTypeArg(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHandle canonTh, TypeHandle th) + // collapse to __Canon; primitives map to their primitive ITypeHandle. + private ITypeHandle ApproxTypeArg(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) { CorElementType et = GetElementType(rts, th); switch (et) { case CorElementType.Ptr: { - TypeHandle referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); - return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + ITypeHandle referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } case CorElementType.Class: @@ -255,7 +255,7 @@ private TypeHandle ApproxTypeArg(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHan // Non-generic types return early — the production walker takes the // nTypeArgs == 0 branch and returns the typeDef directly, which equals the type's // own MT for a non-generic type. - private TypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, TypeHandle canonTh, TypeHandle th) + private ITypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) { // Mirror DacDbiImpl.FillClassTypeInfo: upcast continuation-without-metadata types to // their parent before resolving module / typeDef token. Otherwise the synthesized token @@ -268,7 +268,7 @@ private TypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, T th = rts.GetTypeHandle(parentMT); } - ReadOnlySpan inst = rts.GetInstantiation(th); + ImmutableArray inst = rts.GetInstantiation(th); if (inst.Length == 0) return th; @@ -280,16 +280,16 @@ private TypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, T ulong vmAssembly = loader.GetAssembly(moduleHandle).Value; uint metadataToken = rts.GetTypeDefToken(th); - TypeHandle typeDef = dbi.TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + ITypeHandle typeDef = dbi.TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); if (typeDef.IsNull) - return default; + return ITypeHandle.Null; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(inst.Length); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(inst.Length); for (int i = 0; i < inst.Length; i++) { - TypeHandle approxArg = ApproxTypeArg(dbi, rts, canonTh, inst[i]); + ITypeHandle approxArg = ApproxTypeArg(dbi, rts, canonTh, inst[i]); if (approxArg.IsNull) - return default; + return ITypeHandle.Null; builder.Add(approxArg); } @@ -298,7 +298,7 @@ private TypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, T // Same element-type mapping DacDbiImpl uses (System.String -> E_T_STRING, System.Object -> // E_T_OBJECT, else GetSignatureCorElementType). - private static CorElementType GetElementType(IRuntimeTypeSystem rts, TypeHandle th) + private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle th) { if (th.IsNull) return CorElementType.Void; diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs index 83f0996a2d50ef..1b0418ee891e54 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Immutable; using Microsoft.Diagnostics.DataContractReader.Contracts; using Microsoft.Diagnostics.DataContractReader.Legacy; using Microsoft.Diagnostics.DataContractReader.TestInfrastructure; @@ -108,7 +109,7 @@ private static DebuggerIPCE_BasicTypeData[] BuildArgInfoList(DacDbiImpl dbi, IRu return one; } - ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); + ImmutableArray instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length == 0) return Array.Empty(); diff --git a/src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/Lib/Types.cs b/src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/Lib/Types.cs index a0d033148bf443..3d2ea95a1d7e39 100644 --- a/src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/Lib/Types.cs +++ b/src/native/managed/cdac/tests/StressTests/Debuggees/CrossModule/Lib/Types.cs @@ -22,7 +22,7 @@ public class ManagedHolder /// /// Value type with an embedded GC ref. Exercises the encoder's /// GCDesc-driven REF emission across module boundaries: the -/// argument's TypeHandle resolves through the main module's +/// argument's ITypeHandle resolves through the main module's /// CrossModule.exe metadata, but the field-list walk (and offset /// arithmetic) crosses into this library's MethodTable. /// diff --git a/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs b/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs index d1e9320cce6cfc..742662c4266d4d 100644 --- a/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs @@ -115,7 +115,7 @@ public static void AddMethodDesc(this Mock mock, CodeVersion public static void AddMethodTable(this Mock mock, MockCodeVersions builder, CodeVersionsMockMethodTable methodTable) { - ITypeHandle handle = new ITypeHandle(methodTable.Address); + ITypeHandle handle = new TargetTypeHandle(methodTable.Address); mock.Setup(r => r.GetTypeHandle(methodTable.Address)).Returns(address => { // this is not quite accurate on 32 bit architectures, but it's good enough for testing diff --git a/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs b/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs index 6b9b0ab9fe03fc..7a45d04cfa79e8 100644 --- a/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs @@ -339,8 +339,8 @@ public void IsExceptionObject(MockTarget.Architecture arch, int inheritanceDepth mockRts.Setup(r => r.GetWellKnownMethodTable(WellKnownMethodTable.Exception)).Returns(exceptionMT); if (intermediateMTs.Length == 0 && !isException) { - mockRts.Setup(r => r.GetTypeHandle(objectMT)).Returns(new ITypeHandle(objectMT)); - mockRts.Setup(r => r.GetParentMethodTable(new ITypeHandle(objectMT))).Returns(TargetPointer.Null); + mockRts.Setup(r => r.GetTypeHandle(objectMT)).Returns(new TargetTypeHandle(objectMT)); + mockRts.Setup(r => r.GetParentMethodTable(new TargetTypeHandle(objectMT))).Returns(TargetPointer.Null); } for (int i = 0; i < intermediateMTs.Length; i++) { @@ -349,8 +349,8 @@ public void IsExceptionObject(MockTarget.Architecture arch, int inheritanceDepth ? intermediateMTs[i + 1] : isException ? exceptionMT : TargetPointer.Null; - mockRts.Setup(r => r.GetTypeHandle(current)).Returns(new ITypeHandle(current)); - mockRts.Setup(r => r.GetParentMethodTable(new ITypeHandle(current))).Returns(parent); + mockRts.Setup(r => r.GetTypeHandle(current)).Returns(new TargetTypeHandle(current)); + mockRts.Setup(r => r.GetParentMethodTable(new TargetTypeHandle(current))).Returns(parent); } var (dacDbi, _) = CreateDacDbiWithExceptionMT(arch, mockObject, mockRts); diff --git a/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs b/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs index bece4fcd63501b..a05f5f556251a4 100644 --- a/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs @@ -199,14 +199,14 @@ private static IException CreateContract(MockTarget.Architecture arch, StackTrac Name = "CombinedPtrArray", }); - ITypeHandle combinedHandle = new(CombinedArrayMTAddr); + ITypeHandle combinedHandle = new TargetTypeHandle(CombinedArrayMTAddr); objectMock.Setup(o => o.GetMethodTableAddress(CombinedArrayAddr)).Returns(CombinedArrayMTAddr); rtsMock.Setup(r => r.GetTypeHandle(CombinedArrayMTAddr)).Returns(combinedHandle); rtsMock.Setup(r => r.ContainsGCPointers(combinedHandle)).Returns(true); } else { - ITypeHandle i1Handle = new(StackTraceMTAddr); + ITypeHandle i1Handle = new TargetTypeHandle(StackTraceMTAddr); objectMock.Setup(o => o.GetMethodTableAddress(StackTraceObjectAddr)).Returns(StackTraceMTAddr); rtsMock.Setup(r => r.GetTypeHandle(StackTraceMTAddr)).Returns(i1Handle); rtsMock.Setup(r => r.ContainsGCPointers(i1Handle)).Returns(false); diff --git a/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs b/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs index a8a61d0a8d1a63..ba74f08a00da8f 100644 --- a/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs @@ -395,7 +395,7 @@ public void IsGenericMethodDefinition(MockTarget.Architecture arch) MethodDescHandle handle = rts.GetMethodDescHandle(genericMethodDef); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(rts.IsGenericMethodDefinition(handle)); - ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); + var instantiation = rts.GetGenericMethodInstantiation(handle); Assert.Equal(0, instantiation.Length); } @@ -403,7 +403,7 @@ public void IsGenericMethodDefinition(MockTarget.Architecture arch) MethodDescHandle handle = rts.GetMethodDescHandle(genericWithInst); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(rts.IsGenericMethodDefinition(handle)); - ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); + var instantiation = rts.GetGenericMethodInstantiation(handle); Assert.Equal(typeArgsRawAddrs.Length, instantiation.Length); for (int i = 0; i < typeArgsRawAddrs.Length; i++) { diff --git a/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs b/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs index b7a54248fa60e5..87d018161e084d 100644 --- a/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs @@ -295,7 +295,7 @@ public void GetObjectClassName_UnloadedModule(MockTarget.Architecture arch) }, builder => { var mockRts = new Mock(); - ITypeHandle handle = new ITypeHandle(TestMethodTableAddress); + ITypeHandle handle = new TargetTypeHandle(TestMethodTableAddress); mockRts.Setup(r => r.GetTypeHandle(TestMethodTableAddress)).Returns(handle); mockRts.Setup(r => r.GetModule(handle)).Returns(TargetPointer.Null); @@ -343,7 +343,7 @@ public void GetObjectClassName_NullBufferReturnsNeededSize(MockTarget.Architectu }, builder => { var mockRts = new Mock(); - ITypeHandle handle = new ITypeHandle(TestMethodTableAddress); + ITypeHandle handle = new TargetTypeHandle(TestMethodTableAddress); mockRts.Setup(r => r.GetTypeHandle(TestMethodTableAddress)).Returns(handle); mockRts.Setup(r => r.GetModule(handle)).Returns(TargetPointer.Null); diff --git a/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs b/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs index aa77f85df9c7a2..9058be1b6d3b9c 100644 --- a/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs @@ -45,7 +45,7 @@ private static (Mock Rts, Mock Loader) CreateMocks( ModuleFlags flags) { var rts = new Mock(); - rts.Setup(r => r.GetTypeHandle(mtPtr)).Returns(new ITypeHandle(mtPtr)); + rts.Setup(r => r.GetTypeHandle(mtPtr)).Returns(new TargetTypeHandle(mtPtr)); rts.Setup(r => r.GetModule(It.Is(th => th.Address == mtPtr))).Returns(modulePtr); var loader = new Mock(); diff --git a/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs b/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs index 46fb1d9aa0d0b5..5e5c6bc79f385d 100644 --- a/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs +++ b/src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs @@ -40,7 +40,7 @@ private static ISOSDacInterface5 CreateDac5( ILCodeVersionHandle ilCodeVersion = ILCodeVersionHandle.CreateSynthetic(s_moduleAddr, 0x06000001); MethodDescHandle methodDescHandle = new MethodDescHandle(s_methodDescAddr); - ITypeHandle typeHandle = new ITypeHandle(s_methodTableAddr); + ITypeHandle typeHandle = new TargetTypeHandle(s_methodTableAddr); Contracts.ModuleHandle moduleHandle = new Contracts.ModuleHandle(s_moduleAddr); mockCodeVersions diff --git a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs index 537f77e93fc480..8c606c991b0804 100644 --- a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; using Microsoft.Diagnostics.DataContractReader.Contracts; @@ -161,7 +162,7 @@ public void IsFunctionPointer(MockTarget.Architecture arch) // Function pointer IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); - bool res = rts.IsFunctionPointer(handle, out ReadOnlySpan actualRetAndArgTypes, out SignatureCallingConvention actualCallConv); + bool res = rts.IsFunctionPointer(handle, out ImmutableArray actualRetAndArgTypes, out SignatureCallingConvention actualCallConv); Assert.True(res); Assert.Equal(callConv, (byte)actualCallConv); Assert.Equal(retAndArgTypesHandle.Length, actualRetAndArgTypes.Length); From 26d789ef96c689098ac12ad8a86fb1c0baa7e1e6 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 15:25:08 -0400 Subject: [PATCH 03/23] Address review feedback: accessor name, Equals symmetry, comments, docs - Generator: keep the emitted accessor name TypeHandle (change only its return type to ITypeHandle); update the ComWrappers_1 call site and IData.md. - TargetTypeHandle.Equals: compare by Address so equality is symmetric with NullTypeHandle (honors the IEquatable contract for use as a dictionary key). - SOSDacImpl: restore the native reference comment to TypeHandle::GetMethodTable (the native CoreCLR type is unchanged) and fix 'a' -> 'an'. - Restore the UTF-8 BOM on SigFormat.cs (avoid an encoding-only diff). - CCWDumpTests: grammar 'a' -> 'an'. - Update docs/design/datacontracts/{RuntimeTypeSystem,ManagedTypeSource, Signature,RuntimeMutableTypeSystem}.md to the ITypeHandle / ImmutableArray contract surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../design/datacontracts/ManagedTypeSource.md | 18 +- .../datacontracts/RuntimeMutableTypeSystem.md | 4 +- .../design/datacontracts/RuntimeTypeSystem.md | 317 +++++++++--------- docs/design/datacontracts/Signature.md | 18 +- src/native/managed/cdac/IData.md | 2 +- .../Contracts/ComWrappers_1.cs | 2 +- .../TypeHandleImplementations.cs | 2 +- .../SigFormat.cs | 2 +- src/native/managed/cdac/gen/Emitter.cs | 2 +- .../cdac/tests/DumpTests/CCWDumpTests.cs | 2 +- 10 files changed, 187 insertions(+), 182 deletions(-) diff --git a/docs/design/datacontracts/ManagedTypeSource.md b/docs/design/datacontracts/ManagedTypeSource.md index 2e4b3a3ada9ae3..cf612df51a3094 100644 --- a/docs/design/datacontracts/ManagedTypeSource.md +++ b/docs/design/datacontracts/ManagedTypeSource.md @@ -21,10 +21,10 @@ bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info); // Throws InvalidOperationException if the type cannot be resolved. Target.TypeInfo GetTypeInfo(string fullyQualifiedName); -// Return true and populate `typeHandle` with the runtime TypeHandle for the type, +// Return true and populate `typeHandle` with the runtime ITypeHandle for the type, // or false if the type cannot be resolved. -bool TryGetTypeHandle(string fullyQualifiedName, out TypeHandle typeHandle); -TypeHandle GetTypeHandle(string fullyQualifiedName); +bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle); +ITypeHandle GetTypeHandle(string fullyQualifiedName); // Return true and populate `address` with the address of the named static field, // or false if the type / field cannot be resolved or its statics storage has not @@ -68,7 +68,7 @@ they read in their own `### Managed types used` section. ``` csharp // Type resolution: parse the fully-qualified name, walk System.Private.CoreLib's // metadata to locate the TypeDef, then map TypeDef -> MethodTable via the loader. -bool TryResolveType(string managedFqName, out TypeHandle th, out MetadataReader mdReader, out TypeDefinition typeDef) +bool TryResolveType(string managedFqName, out ITypeHandle th, out MetadataReader mdReader, out TypeDefinition typeDef) { ILoader loader = target.Contracts.Loader; TargetPointer systemAssembly = loader.GetSystemAssembly(); @@ -96,14 +96,14 @@ bool TryResolveType(string managedFqName, out TypeHandle th, out MetadataReader return true; } -bool TryGetTypeHandle(string fqn, out TypeHandle th) +bool TryGetTypeHandle(string fqn, out ITypeHandle th) { return TryResolveType(fqn, out th, out _, out _); } bool TryGetTypeInfo(string fqn, out Target.TypeInfo info) { - if (!TryResolveType(fqn, out TypeHandle th, out MetadataReader mdReader, out TypeDefinition typeDef)) + if (!TryResolveType(fqn, out ITypeHandle th, out MetadataReader mdReader, out TypeDefinition typeDef)) return false; IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; @@ -147,7 +147,7 @@ bool TryGetStaticFieldAddress(string fqn, string fieldName, out TargetPointer ad // cannot dereference a small offset-from-zero when the class has not been // initialized. TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fdAddr); - TypeHandle ctx = rts.GetTypeHandle(enclosingMT); + ITypeHandle ctx = rts.GetTypeHandle(enclosingMT); CorElementType et = rts.GetFieldDescType(fdAddr); bool isGC = et is CorElementType.Class or CorElementType.ValueType; TargetPointer @base = isGC @@ -174,7 +174,7 @@ bool TryGetThreadStaticFieldAddress(string fqn, string fieldName, TargetPointer // thread so callers cannot dereference a small offset-from-zero when this // thread has not initialized thread-static storage for the type. TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fdAddr); - TypeHandle ctx = rts.GetTypeHandle(enclosingMT); + ITypeHandle ctx = rts.GetTypeHandle(enclosingMT); CorElementType et = rts.GetFieldDescType(fdAddr); bool isGC = et is CorElementType.Class or CorElementType.ValueType; TargetPointer @base = isGC @@ -189,7 +189,7 @@ bool TryGetThreadStaticFieldAddress(string fqn, string fieldName, TargetPointer bool TryGetFieldDesc(string fqn, string fieldName, out TargetPointer fdAddr) { - if (!TryResolveType(fqn, out TypeHandle th, out _, out _)) + if (!TryResolveType(fqn, out ITypeHandle th, out _, out _)) { fdAddr = TargetPointer.Null; return false; diff --git a/docs/design/datacontracts/RuntimeMutableTypeSystem.md b/docs/design/datacontracts/RuntimeMutableTypeSystem.md index b4a9d70d080f08..fc86e4d7d38793 100644 --- a/docs/design/datacontracts/RuntimeMutableTypeSystem.md +++ b/docs/design/datacontracts/RuntimeMutableTypeSystem.md @@ -5,7 +5,7 @@ This contract exposes runtime type system information about changes that occurre ## APIs of contract ```csharp -IEnumerable EnumerateAddedFieldDescs(TypeHandle typeHandle, bool staticFields); +IEnumerable EnumerateAddedFieldDescs(ITypeHandle typeHandle, bool staticFields); bool IsFieldDescEnCNew(TargetPointer fieldDescPointer); bool DoesEnCFieldDescNeedFixup(TargetPointer encFieldDescPointer); TargetPointer GetEnCStaticFieldDataAddress(TargetPointer encFieldDescPointer); @@ -59,7 +59,7 @@ internal enum FieldDescFlags2 : uint OffsetMask = 0x07ffffff, } -IEnumerable EnumerateAddedFieldDescs(TypeHandle typeHandle, bool staticFields) +IEnumerable EnumerateAddedFieldDescs(ITypeHandle typeHandle, bool staticFields) { // get modulePtr and moduleHandle from typeHandle // if there is no EnC data, yield break diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index 79fb1a546a2ee4..2c425ef16077ab 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -4,20 +4,25 @@ This contract is for exploring the properties of the runtime types of values on ## APIs of contract -### TypeHandle +### ITypeHandle -A `TypeHandle` is the runtime representation of the type information about a value which is represented as a TypeHandle. -Given a `TargetPointer` address, the `RuntimeTypeSystem` contract provides a `TypeHandle` for querying the details of the `TypeHandle`. +An `ITypeHandle` is the runtime representation of the type information about a value which is represented as an `ITypeHandle`. +Given a `TargetPointer` address, the `RuntimeTypeSystem` contract provides an `ITypeHandle` for querying the details of the type. ``` csharp -struct TypeHandle +// An opaque handle to a runtime type, backed by a target-process MethodTable or TypeDesc address. +interface ITypeHandle : IEquatable { - // no public constructors + TargetPointer Address { get; } + bool IsNull { get; } - public TargetPointer Address { get; } - public bool IsNull => Address != 0; + // Sentinel handle representing the absence of a type (Address == 0). + static ITypeHandle Null { get; } } +// A real target-backed handle (a MethodTable* or TypeDesc* address). +class TargetTypeHandle : ITypeHandle { /* ... */ } + readonly record struct TypedByRefInfo(TargetPointer Data, TargetPointer TypeHandle); internal enum CorElementType @@ -29,121 +34,121 @@ internal enum CorElementType } ``` -A `TypeHandle` is the runtime representation of the type information about a value. This can be constructed from the address of a `TypeHandle` or a `MethodTable`. +A `ITypeHandle` is the runtime representation of the type information about a value. This can be constructed from the address of a `ITypeHandle` or a `MethodTable`. ``` csharp partial interface IRuntimeTypeSystem : IContract { #region TypeHandle inspection APIs - public virtual TypeHandle GetTypeHandle(TargetPointer targetPointer); + public virtual ITypeHandle GetTypeHandle(TargetPointer targetPointer); - public virtual TargetPointer GetModule(TypeHandle typeHandle); + public virtual TargetPointer GetModule(ITypeHandle typeHandle); // A canonical method table is either the MethodTable itself, or in the case of a generic instantiation, it is the // MethodTable of the prototypical instance. - public virtual TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle); + public virtual TargetPointer GetCanonicalMethodTable(ITypeHandle typeHandle); // True if this MethodTable is the canonical MethodTable (i.e., EEClassOrCanonMT points directly to the EEClass) - public virtual bool IsCanonicalMethodTable(TypeHandle typeHandle); - public virtual TargetPointer GetParentMethodTable(TypeHandle typeHandle); + public virtual bool IsCanonicalMethodTable(ITypeHandle typeHandle); + public virtual TargetPointer GetParentMethodTable(ITypeHandle typeHandle); - public virtual TargetPointer GetMethodDescForSlot(TypeHandle typeHandle, ushort slot); - public virtual IEnumerable GetIntroducedMethodDescs(TypeHandle methodTable); - public virtual TargetCodePointer GetSlot(TypeHandle typeHandle, uint slot); + public virtual TargetPointer GetMethodDescForSlot(ITypeHandle typeHandle, ushort slot); + public virtual IEnumerable GetIntroducedMethodDescs(ITypeHandle methodTable); + public virtual TargetCodePointer GetSlot(ITypeHandle typeHandle, uint slot); - public virtual uint GetBaseSize(TypeHandle typeHandle); + public virtual uint GetBaseSize(ITypeHandle typeHandle); // The number of bytes of instance fields stored in an object of this type on the GC heap. // Equivalent to the native MethodTable::GetNumInstanceFieldBytes(), which is computed as // GetBaseSize() minus the EEClass base-size padding (the trailing alignment/min-object-size // bytes included in BaseSize but not occupied by actual instance fields). - public virtual uint GetNumInstanceFieldBytes(TypeHandle typeHandle); + public virtual uint GetNumInstanceFieldBytes(ITypeHandle typeHandle); // The component size is only available for strings and arrays. It is the size of the element type of the array, or the size of an ECMA 335 character (2 bytes) - public virtual uint GetComponentSize(TypeHandle typeHandle); + public virtual uint GetComponentSize(ITypeHandle typeHandle); // True if the MethodTable is the sentinel value associated with unallocated space in the managed heap - public virtual bool IsFreeObjectMethodTable(TypeHandle typeHandle); + public virtual bool IsFreeObjectMethodTable(ITypeHandle typeHandle); // True if the MethodTable is the System.Object MethodTable (g_pObjectClass) - public virtual bool IsObject(TypeHandle typeHandle); - public virtual bool IsString(TypeHandle typeHandle); + public virtual bool IsObject(ITypeHandle typeHandle); + public virtual bool IsString(ITypeHandle typeHandle); // True if the CorElementType represents a GC-collectable object reference. public virtual bool IsCorElementTypeObjRef(CorElementType elementType); // Returns the address of one of the runtime's well-known singleton MethodTables, or // TargetPointer.Null if the runtime has not yet initialized that global. public virtual TargetPointer GetWellKnownMethodTable(WellKnownMethodTable kind); // True if the MethodTable represents a type that contains managed references - public virtual bool ContainsGCPointers(TypeHandle typeHandle); + public virtual bool ContainsGCPointers(ITypeHandle typeHandle); // True if the MethodTable represents a byref-like value type (Span, ReadOnlySpan, any ref struct). - public virtual bool IsByRefLike(TypeHandle typeHandle); + public virtual bool IsByRefLike(ITypeHandle typeHandle); // If the type is an HFA (or HVA on ARM64), returns true and sets elementSize // to 4, 8, or 16. Returns false otherwise (including on targets that don't // define FEATURE_HFA). Mirrors MethodTable::GetHFAType in // src/coreclr/vm/class.cpp. - public virtual bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize); + public virtual bool TryGetHFAElementSize(ITypeHandle typeHandle, out int elementSize); // True if the type requires 8-byte alignment on platforms that don't 8-byte align by default (FEATURE_64BIT_ALIGNMENT) - public virtual bool RequiresAlign8(TypeHandle typeHandle); + public virtual bool RequiresAlign8(ITypeHandle typeHandle); // Returns the cached SystemV AMD64 eightbyte register-passing classification for a value type // (used to decide how a struct is passed in registers), or false if the type has no such // classification (not applicable, or the runtime was not built with UNIX_AMD64_ABI). - public virtual bool TryGetSystemVAmd64EightByteClassification(TypeHandle typeHandle, out SystemVAmd64EightByteClassification classification); + public virtual bool TryGetSystemVAmd64EightByteClassification(ITypeHandle typeHandle, out SystemVAmd64EightByteClassification classification); // True if the MethodTable represents a continuation type used by the async continuation feature - public virtual bool IsContinuationWithoutMetadata(TypeHandle typeHandle); + public virtual bool IsContinuationWithoutMetadata(ITypeHandle typeHandle); // Returns the GC pointer runs for the method table as (offset, size) pairs. Each // run starts Offset bytes from the object pointer (`this`), where offset 0 // is the method table pointer, and includes Size bytes of contiguous pointers // For handles representing value types the object is assumed to be stored in the boxed layout. - public virtual IEnumerable<(uint Offset, uint Size)> GetGCDescSeries(TypeHandle typeHandle, uint numComponents = 0); - public virtual bool IsDynamicStatics(TypeHandle typeHandle); - public virtual ushort GetNumInterfaces(TypeHandle typeHandle); + public virtual IEnumerable<(uint Offset, uint Size)> GetGCDescSeries(ITypeHandle typeHandle, uint numComponents = 0); + public virtual bool IsDynamicStatics(ITypeHandle typeHandle); + public virtual ushort GetNumInterfaces(ITypeHandle 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 GetNumVtableSlots(TypeHandle typeHandle); - public virtual ushort GetNumMethods(TypeHandle typeHandle); + public virtual uint GetTypeDefToken(ITypeHandle typeHandle); + public virtual ushort GetNumVtableSlots(ITypeHandle typeHandle); + public virtual ushort GetNumMethods(ITypeHandle 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 GetGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr); - public TargetPointer GetNonGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr); - public IEnumerable GetFieldDescList(TypeHandle typeHandle); + public virtual uint GetTypeDefTypeAttributes(ITypeHandle typeHandle); + public ushort GetNumInstanceFields(ITypeHandle typeHandle); + public ushort GetNumStaticFields(ITypeHandle typeHandle); + public ushort GetNumThreadStaticFields(ITypeHandle typeHandle); + public TargetPointer GetGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr); + public TargetPointer GetNonGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr); + public IEnumerable GetFieldDescList(ITypeHandle typeHandle); // True if the MethodTable represents a type tracked as an Objective-C reference type with a finalizer - public bool IsTrackedReferenceWithFinalizer(TypeHandle typeHandle); - public TargetPointer GetGCStaticsBasePointer(TypeHandle typeHandle); - public TargetPointer GetNonGCStaticsBasePointer(TypeHandle typeHandle); - public virtual ReadOnlySpan GetInstantiation(TypeHandle typeHandle); - public bool IsClassInited(TypeHandle typeHandle); - public bool IsInitError(TypeHandle typeHandle); - public virtual bool IsGenericTypeDefinition(TypeHandle typeHandle); - - public virtual bool IsCollectible(TypeHandle typeHandle); - public virtual bool ContainsGenericVariables(TypeHandle typeHandle); - public virtual bool HasTypeParam(TypeHandle typeHandle); + public bool IsTrackedReferenceWithFinalizer(ITypeHandle typeHandle); + public TargetPointer GetGCStaticsBasePointer(ITypeHandle typeHandle); + public TargetPointer GetNonGCStaticsBasePointer(ITypeHandle typeHandle); + public virtual ImmutableArray GetInstantiation(ITypeHandle typeHandle); + public bool IsClassInited(ITypeHandle typeHandle); + public bool IsInitError(ITypeHandle typeHandle); + public virtual bool IsGenericTypeDefinition(ITypeHandle typeHandle); + + public virtual bool IsCollectible(ITypeHandle typeHandle); + public virtual bool ContainsGenericVariables(ITypeHandle typeHandle); + public virtual bool HasTypeParam(ITypeHandle typeHandle); // Element type of the type. NOTE: this drops the CorElementType.GenericInst, and CorElementType.String is returned as CorElementType.Class. // NOTE: If this returns CorElementType.ValueType it may be a normal valuetype or a "NATIVE" valuetype used to represent an interop view of a structure // HasTypeParam will return true for cases where this is the interop view, and false for normal valuetypes. - public virtual CorElementType GetSignatureCorElementType(TypeHandle typeHandle); + public virtual CorElementType GetSignatureCorElementType(ITypeHandle typeHandle); // Internal element type of the type. Unlike GetSignatureCorElementType, this returns the underlying // primitive type for enums (e.g. I4 for an enum with int underlying type). // For arrays, reference types, and TypeDescs, behaves identically to GetSignatureCorElementType. - public virtual CorElementType GetInternalCorElementType(TypeHandle typeHandle); + public virtual CorElementType GetInternalCorElementType(ITypeHandle typeHandle); - bool IsValueType(TypeHandle typeHandle); + bool IsValueType(ITypeHandle typeHandle); // return true if the TypeHandle represents an enum type. - bool IsEnum(TypeHandle typeHandle); + bool IsEnum(ITypeHandle typeHandle); // return true if the TypeHandle represents a delegate type (i.e., its parent is System.MulticastDelegate) - bool IsDelegate(TypeHandle typeHandle); + bool IsDelegate(ITypeHandle typeHandle); // return true if the TypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. - bool IsArray(TypeHandle typeHandle, out uint rank); - TypeHandle GetTypeParam(TypeHandle typeHandle); - TypeHandle GetConstructedType(TypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default); - TypeHandle GetPrimitiveType(CorElementType typeCode); - bool IsGenericVariable(TypeHandle typeHandle, out TargetPointer module, out uint token); - bool IsFunctionPointer(TypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv); - bool IsPointer(TypeHandle typeHandle); - bool IsTypeDesc(TypeHandle typeHandle); - TargetPointer GetLoaderModule(TypeHandle typeHandle); + bool IsArray(ITypeHandle typeHandle, out uint rank); + ITypeHandle GetTypeParam(ITypeHandle typeHandle); + ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default); + ITypeHandle GetPrimitiveType(CorElementType typeCode); + bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token); + bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv); + bool IsPointer(ITypeHandle typeHandle); + bool IsTypeDesc(ITypeHandle typeHandle); + TargetPointer GetLoaderModule(ITypeHandle typeHandle); TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef); #endregion TypeHandle inspection APIs @@ -218,7 +223,7 @@ partial interface IRuntimeTypeSystem : IContract // Return true for an uninstantiated generic method public virtual bool IsGenericMethodDefinition(MethodDescHandle methodDesc); - public virtual ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDesc); + public virtual ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDesc); // Return mdTokenNil (0x06000000) if the method doesn't have a token, otherwise return the token of the method public virtual uint GetMethodToken(MethodDescHandle methodDesc); @@ -314,7 +319,7 @@ bool IsFieldDescStatic(TargetPointer fieldDescPointer); bool IsFieldDescRVA(TargetPointer fieldDescPointer); CorElementType GetFieldDescType(TargetPointer fieldDescPointer); uint GetFieldDescOffset(TargetPointer fieldDescPointer, FieldDefinition? fieldDef); -TypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer); +ITypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer); bool TryGetFieldDescNext(TargetPointer fieldDescPointer, out TargetPointer nextFieldDesc); TargetPointer GetFieldDescStaticAddress(TargetPointer fieldDescPointer, bool unboxValueTypes = true); TargetPointer GetFieldDescThreadStaticAddress(TargetPointer fieldDescPointer, TargetPointer thread, bool unboxValueTypes = true); @@ -327,7 +332,7 @@ void GetCoreLibFieldDescAndDef(string @namespace, string typeName, string fieldN ## Version 1 -### TypeHandle +### ITypeHandle The `MethodTable` inspection APIs are implemented in terms of the following flags on the runtime `MethodTable` structure: @@ -479,7 +484,7 @@ internal struct MethodTable_1 } ``` -Internally the contract uses extension methods on the `TypeHandle` api so that it can distinguish between `MethodTable` and `TypeDesc` +Internally the contract uses extension methods on the `ITypeHandle` api so that it can distinguish between `MethodTable` and `TypeDesc` ```csharp static class RuntimeTypeSystem_1_Helpers { @@ -568,7 +573,7 @@ The contract additionally depends on these data descriptors | `LoaderAllocator` | `IsCollectible` | Non-zero if the `LoaderAllocator` is collectible. | | `LoaderAllocator` | `CreationNumber` | Monotonically-increasing creation number assigned to each collectible `LoaderAllocator`. | | `TypedByRef` | `Data` | Managed pointer (the byref) stored in a `System.TypedReference` value | -| `TypedByRef` | `Type` | Raw `TypeHandle` pointer of the referent type | +| `TypedByRef` | `Type` | Raw `ITypeHandle` pointer of the referent type | The value of the `NativeCodeVersionNode::OptimizationTier` field is one of: ```csharp @@ -603,7 +608,7 @@ Contracts used: internal TargetPointer ContinuationMethodTablePointer {get; } private TargetPointer _continuationSingletonEEClassPointer; - public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) + public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) { ... // validate that typeHandlePointer points to something that looks like a MethodTable or a TypeDesc. ... // If this is a MethodTable @@ -612,7 +617,7 @@ Contracts used: return TypeHandle { Address = typeHandlePointer } } - public TargetPointer GetModule(TypeHandle TypeHandle) + public TargetPointer GetModule(ITypeHandle TypeHandle) { if (typeHandle.IsMethodTable()) { @@ -637,17 +642,17 @@ Contracts used: return (EEClassOrCanonMTBits)(eeClassOrCanonMTPtr & (ulong)EEClassOrCanonMTBits.Mask); } - public TargetPointer GetCanonicalMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable; + public TargetPointer GetCanonicalMethodTable(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable; - public TargetPointer GetParentMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[TypeHandle.Address].ParentMethodTable; + public TargetPointer GetParentMethodTable(ITypeHandle 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 GetBaseSize(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[TypeHandle.Address].Flags.BaseSize; - public uint GetNumInstanceFieldBytes(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[TypeHandle.Address].Flags.BaseSize - GetClassData(TypeHandle).BaseSizePadding; + public uint GetNumInstanceFieldBytes(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[TypeHandle.Address].Flags.BaseSize - GetClassData(TypeHandle).BaseSizePadding; - public uint GetComponentSize(TypeHandle TypeHandle) =>!typeHandle.IsMethodTable() ? (uint)0 : GetComponentSize(_methodTables[TypeHandle.Address]); + public uint GetComponentSize(ITypeHandle TypeHandle) =>!typeHandle.IsMethodTable() ? (uint)0 : GetComponentSize(_methodTables[TypeHandle.Address]); - private TargetPointer GetClassPointer(TypeHandle TypeHandle) + private TargetPointer GetClassPointer(ITypeHandle TypeHandle) { // Returns TargetPointer.Null if not a MethodTable. // If EEClassOrCanonMT points directly to an EEClass, returns that pointer. @@ -655,13 +660,13 @@ Contracts used: // the canonical MT and returns its EEClass pointer. } - private Data.EEClass GetClassData(TypeHandle TypeHandle) + private Data.EEClass GetClassData(ITypeHandle TypeHandle) { TargetPointer eeClassPtr = GetClassPointer(TypeHandle); ... // read Data.EEClass data from eeClassPtr } - public bool TryGetSystemVAmd64EightByteClassification(TypeHandle typeHandle, out SystemVAmd64EightByteClassification classification) + public bool TryGetSystemVAmd64EightByteClassification(ITypeHandle typeHandle, out SystemVAmd64EightByteClassification classification) { classification = default; if (!typeHandle.IsMethodTable()) @@ -686,11 +691,11 @@ Contracts used: // present; Second is present only when numEightBytes > 1). Return true. } - public bool IsFreeObjectMethodTable(TypeHandle TypeHandle) => FreeObjectMethodTablePointer == TypeHandle.Address; + public bool IsFreeObjectMethodTable(ITypeHandle TypeHandle) => FreeObjectMethodTablePointer == TypeHandle.Address; - public bool IsObject(TypeHandle TypeHandle) => ObjectMethodTablePointer != TargetPointer.Null && ObjectMethodTablePointer == TypeHandle.Address; + public bool IsObject(ITypeHandle TypeHandle) => ObjectMethodTablePointer != TargetPointer.Null && ObjectMethodTablePointer == TypeHandle.Address; - public bool IsString(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsString; + public bool IsString(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsString; public bool IsCorElementTypeObjRef(CorElementType elementType) => elementType is CorElementType.Class @@ -721,9 +726,9 @@ Contracts used: return value; } - public bool ContainsGCPointers(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.ContainsGCPointers; + public bool ContainsGCPointers(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.ContainsGCPointers; - public bool IsByRefLike(TypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsByRefLike; + public bool IsByRefLike(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsByRefLike; // Mirrors MethodTable::GetHFAType in src/coreclr/vm/class.cpp. Pseudocode: // @@ -752,20 +757,20 @@ Contracts used: // _: return 0 // if !CorIsNumericalType(GetInstantiation(mt)[0]): return 0 // return elem - public bool TryGetHFAElementSize(TypeHandle typeHandle, out int elementSize) { ... } + public bool TryGetHFAElementSize(ITypeHandle typeHandle, out int elementSize) { ... } - public bool RequiresAlign8(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.RequiresAlign8; + public bool RequiresAlign8(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.RequiresAlign8; - public bool IsCanonicalMethodTable(TypeHandle typeHandle) + public bool IsCanonicalMethodTable(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].IsCanonMT; - public bool IsContinuationWithoutMetadata(TypeHandle typeHandle) => typeHandle.IsMethodTable() + public bool IsContinuationWithoutMetadata(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && ContinuationMethodTablePointer != TargetPointer.Null && _methodTables[typeHandle.Address].ParentMethodTable == ContinuationMethodTablePointer && _continuationSingletonEEClassPointer != TargetPointer.Null && GetClassPointer(typeHandle) == _continuationSingletonEEClassPointer; - IEnumerable<(uint Offset, uint Size)> GetGCDescSeries(TypeHandle typeHandle, uint numComponents = 0) + IEnumerable<(uint Offset, uint Size)> GetGCDescSeries(ITypeHandle typeHandle, uint numComponents = 0) { // Returns empty if not a method table or has no GC pointers. // Compute objectSize: baseSize + numComponents * componentSize. @@ -816,11 +821,11 @@ Contracts used: // currentOffset += nptrs * pointerSize + skip } - public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics; + public bool IsDynamicStatics(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics; - public ushort GetNumInterfaces(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces; + public ushort GetNumInterfaces(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces; - public uint GetTypeDefToken(TypeHandle TypeHandle) + public uint GetTypeDefToken(ITypeHandle TypeHandle) { if (!typeHandle.IsMethodTable()) return 0; @@ -829,7 +834,7 @@ Contracts used: return (uint)(typeHandle.Flags.GetTypeDefRid() | ((int)TableIndex.TypeDef << 24)); } - public ushort GetNumVtableSlots(TypeHandle typeHandle) + public ushort GetNumVtableSlots(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return 0; @@ -838,17 +843,17 @@ Contracts used: return checked((ushort)(methodTable.NumVirtuals + numNonVirtualSlots)); } - public ushort GetNumMethods(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).NumMethods; + public ushort GetNumMethods(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).NumMethods; - public uint GetTypeDefTypeAttributes(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).CorTypeAttr; + public uint GetTypeDefTypeAttributes(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).CorTypeAttr; - public ushort GetNumInstanceFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields; + public ushort GetNumInstanceFields(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields; - public ushort GetNumStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields; + public ushort GetNumStaticFields(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields; - public ushort GetNumThreadStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields; + public ushort GetNumThreadStaticFields(ITypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields; - public IEnumerable GetFieldDescList(TypeHandle typeHandle) + public IEnumerable GetFieldDescList(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) yield break; @@ -860,7 +865,7 @@ Contracts used: TargetPointer parentMT = GetParentMethodTable(typeHandle); if (parentMT != TargetPointer.Null) { - TypeHandle parentHandle = GetTypeHandle(parentMT); + ITypeHandle parentHandle = GetTypeHandle(parentMT); numInstanceFields -= GetNumInstanceFields(parentHandle); } int totalFields = numInstanceFields + GetNumStaticFields(typeHandle); @@ -870,9 +875,9 @@ Contracts used: } } - public bool IsTrackedReferenceWithFinalizer(TypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsTrackedReferenceWithFinalizer; + public bool IsTrackedReferenceWithFinalizer(ITypeHandle typeHandle) => typeHandle.IsMethodTable() && _methodTables[typeHandle.Address].Flags.IsTrackedReferenceWithFinalizer; - public TargetPointer GetGCStaticsBasePointer(TypeHandle typeHandle) + public TargetPointer GetGCStaticsBasePointer(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -887,7 +892,7 @@ Contracts used: return (target.ReadPointer(dynamicStaticsInfo + /* DynamicStaticsInfo::GCStatics offset */) & (ulong)mask); } - public TargetPointer GetNonGCStaticsBasePointer(TypeHandle typeHandle) + public TargetPointer GetNonGCStaticsBasePointer(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -902,7 +907,7 @@ Contracts used: return (target.ReadPointer(dynamicStaticsInfo + /* DynamicStaticsInfo::NonGCStatics offset */) & (ulong)mask); } - public TargetPointer GetGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr) + public TargetPointer GetGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -915,7 +920,7 @@ Contracts used: return threadContract.GetThreadLocalStaticBase(threadPtr, tlsIndexAddr); } - public TargetPointer GetNonGCThreadStaticsBasePointer(TypeHandle typeHandle, TargetPointer threadPtr) + public TargetPointer GetNonGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) { if (!typeHandle.IsMethodTable()) return TargetPointer.Null; @@ -928,7 +933,7 @@ Contracts used: return threadContract.GetThreadLocalStaticBase(threadPtr, tlsIndexAddr); } - public ReadOnlySpan GetInstantiation(TypeHandle TypeHandle) + public ImmutableArray GetInstantiation(ITypeHandle TypeHandle) { if (!typeHandle.IsMethodTable()) return default; @@ -942,14 +947,14 @@ Contracts used: TargetPointer dictionaryPointer = _target.ReadPointer(perInstInfo); int NumTypeArgs = // Read NumTypeArgs from genericsDictInfo using GenericsDictInfo contract - TypeHandle[] instantiation = new TypeHandle[NumTypeArgs]; + ITypeHandle[] instantiation = new ITypeHandle[NumTypeArgs]; for (int i = 0; i < NumTypeArgs; i++) instantiation[i] = GetTypeHandle(_target.ReadPointer(dictionaryPointer + _target.PointerSize * i)); return instantiation; } - public bool IsClassInited(TypeHandle typeHandle) + public bool IsClassInited(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -959,7 +964,7 @@ Contracts used: return (flags & (uint)MethodTableAuxiliaryFlags.Initialized) != 0; } - public bool IsInitError(TypeHandle typeHandle) + public bool IsInitError(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -969,9 +974,9 @@ Contracts used: return (flags & (uint)MethodTableAuxiliaryFlags.IsInitError) != 0; } - public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics; + public bool IsDynamicStatics(ITypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics; - public bool IsCollectible(TypeHandle typeHandle) + public bool IsCollectible(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -979,7 +984,7 @@ Contracts used: return typeHandle.Flags.IsCollectible; } - public bool ContainsGenericVariables(TypeHandle typeHandle) + public bool ContainsGenericVariables(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) return _methodTables[typeHandle.Address].Flags.ContainsGenericVariables; @@ -987,7 +992,7 @@ Contracts used: // recurse through GetTypeParam; for FnPtr, check each signature type argument. } - public bool HasTypeParam(TypeHandle typeHandle) + public bool HasTypeParam(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1009,7 +1014,7 @@ Contracts used: return false; } - public CorElementType GetSignatureCorElementType(TypeHandle typeHandle) + public CorElementType GetSignatureCorElementType(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1040,7 +1045,7 @@ Contracts used: } // Internal element type: returns the underlying primitive type for enums. For all other types, identical to GetSignatureCorElementType. - public CorElementType GetInternalCorElementType(TypeHandle typeHandle) + public CorElementType GetInternalCorElementType(ITypeHandle typeHandle) { CorElementType sigType = GetSignatureCorElementType(typeHandle); if (sigType == CorElementType.ValueType && typeHandle.IsMethodTable()) @@ -1052,7 +1057,7 @@ Contracts used: return sigType; } - public bool IsValueType(TypeHandle typeHandle) + public bool IsValueType(ITypeHandle typeHandle) { // if methodtable: check WFLAGS_HIGH for Category_ValueType // if typedesc: check for CorElementType.ValueType @@ -1061,7 +1066,7 @@ Contracts used: // Enums have Category_Primitive in their MethodTable flags and their // InternalCorElementType is a primitive type (I1, U1, I2, U2, I4, U4, I8, U8), // not ValueType. Regular primitive value types (Int32, etc.) have Category_TruePrimitive. - public bool IsEnum(TypeHandle typeHandle) + public bool IsEnum(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -1070,7 +1075,7 @@ Contracts used: return methodTable.Flags.GetFlag(WFLAGS_HIGH.Category_Mask) == WFLAGS_HIGH.Category_Primitive; } - public bool IsDelegate(TypeHandle typeHandle) + public bool IsDelegate(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) return false; @@ -1080,7 +1085,7 @@ Contracts used: } // return true if the TypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. - public bool IsArray(TypeHandle typeHandle, out uint rank) + public bool IsArray(ITypeHandle typeHandle, out uint rank) { if (typeHandle.IsMethodTable()) { @@ -1104,7 +1109,7 @@ Contracts used: return false; } - public TypeHandle GetTypeParam(TypeHandle typeHandle) + public ITypeHandle GetTypeParam(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1135,9 +1140,9 @@ Contracts used: // helper functions - private bool GenericInstantiationMatch(TypeHandle genericType, TypeHandle potentialMatch, ImmutableArray typeArguments) + private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle potentialMatch, ImmutableArray typeArguments) { - ReadOnlySpan instantiation = GetInstantiation(potentialMatch); + ImmutableArray instantiation = GetInstantiation(potentialMatch); if (instantiation.Length != typeArguments.Length) return false; @@ -1155,7 +1160,7 @@ Contracts used: return true; } - private bool ArrayPtrMatch(TypeHandle elementType, CorElementType corElementType, int rank, TypeHandle potentialMatch) + private bool ArrayPtrMatch(ITypeHandle elementType, CorElementType corElementType, int rank, ITypeHandle potentialMatch) { IsArray(potentialMatch, out uint typeHandleRank); return GetSignatureCorElementType(potentialMatch) == corElementType && @@ -1165,9 +1170,9 @@ Contracts used: } - private bool FnPtrMatch(TypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) + private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) { - if (!IsFunctionPointer(candidate, out ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) + if (!IsFunctionPointer(candidate, out ImmutableArray candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) return false; if (candidateCallConv != callConv) return false; @@ -1181,7 +1186,7 @@ Contracts used: return true; } - private bool IsLoaded(TypeHandle typeHandle) + private bool IsLoaded(ITypeHandle typeHandle) { if (typeHandle.Address == TargetPointer.Null) return false; @@ -1196,15 +1201,15 @@ Contracts used: return (flags & (uint)MethodTableAuxiliaryFlags.IsNotFullyLoaded) == 0; } - TypeHandle GetConstructedType(TypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) + ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) { // For function pointers the type handle arg is unused - type information is provided in the type arguments. if (corElementType != CorElementType.FnPtr && typeHandle.Address == TargetPointer.Null) - return new TypeHandle(TargetPointer.Null); + return ITypeHandle.Null; ILoader loaderContract = _target.Contracts.Loader; TargetPointer loaderModule = // see [link](https://github.com/dotnet/runtime/blob/e1979b72ccb5f916649f1d9949ef663254790c25/src/coreclr/vm/clsload.cpp#L78) ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(loaderModule); - TypeHandle potentialMatch = new TypeHandle(TargetPointer.Null); + ITypeHandle potentialMatch = ITypeHandle.Null; foreach (TargetPointer ptr in loaderContract.GetAvailableTypeParams(moduleHandle)) { potentialMatch = GetTypeHandle(ptr); @@ -1227,10 +1232,10 @@ Contracts used: return potentialMatch; } } - return new TypeHandle(TargetPointer.Null); + return ITypeHandle.Null; } - public TypeHandle GetPrimitiveType(CorElementType typeCode) + public ITypeHandle GetPrimitiveType(CorElementType typeCode) { TargetPointer coreLib = _target.ReadGlobalPointer("CoreLib"); TargetPointer classes = _target.ReadPointer(coreLib + /* CoreLibBinder::Classes offset */); @@ -1238,7 +1243,7 @@ Contracts used: return GetTypeHandle(typeHandlePtr); } - public bool IsGenericVariable(TypeHandle typeHandle, out TargetPointer module, out uint token) + public bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token) { module = TargetPointer.Null; token = 0; @@ -1260,7 +1265,7 @@ Contracts used: return false; } - public bool IsFunctionPointer(TypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) + public bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv) { retAndArgTypes = default; callConv = default; @@ -1277,7 +1282,7 @@ Contracts used: int NumArgs = // Read NumArgs field from FnPtrTypeDesc contract using address typeHandle.TypeDescAddress() TargetPointer RetAndArgTypes = // Read NumArgs field from FnPtrTypeDesc contract using address typeHandle.TypeDescAddress() - TypeHandle[] retAndArgTypesArray = new TypeHandle[NumTypeArgs + 1]; + ITypeHandle[] retAndArgTypesArray = new ITypeHandle[NumTypeArgs + 1]; for (int i = 0; i <= NumTypeArgs; i++) retAndArgTypesArray[i] = GetTypeHandle(_target.ReadPointer(RetAndArgTypes + _target.PointerSize * i)); @@ -1286,7 +1291,7 @@ Contracts used: return true; } - public bool IsPointer(TypeHandle typeHandle) + public bool IsPointer(ITypeHandle typeHandle) { if (!typeHandle.IsTypeDesc()) return false; @@ -1296,9 +1301,9 @@ Contracts used: return elemType == CorElementType.Ptr; } - public bool IsTypeDesc(TypeHandle typeHandle) => typeHandle.IsTypeDesc(); + public bool IsTypeDesc(ITypeHandle typeHandle) => typeHandle.IsTypeDesc(); - public TargetPointer GetLoaderModule(TypeHandle typeHandle) + public TargetPointer GetLoaderModule(ITypeHandle typeHandle) { if (typeHandle.IsTypeDesc()) { @@ -1592,7 +1597,7 @@ And the various apis are implemented with the following algorithms return ((int)Flags2 & (int)InstantiatedMethodDescFlags2.KindMask) == (int)InstantiatedMethodDescFlags2.GenericMethodDefinition; } - public ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) + public ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) { MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; @@ -1604,7 +1609,7 @@ And the various apis are implemented with the following algorithms return default; int NumTypeArgs = // Read NumGenericArgs from methodDescHandle.Address using InstantiatedMethodDesc contract - TypeHandle[] instantiation = new TypeHandle[NumTypeArgs]; + ITypeHandle[] instantiation = new ITypeHandle[NumTypeArgs]; for (int i = 0; i < NumTypeArgs; i++) instantiation[i] = GetTypeHandle(_target.ReadPointer(dictionaryPointer + _target.PointerSize * i)); @@ -1818,12 +1823,12 @@ Determining if a method is in a collectible module: else { TargetPointer mtAddr = GetMethodTable(new MethodDescHandle(md.Address)); - TypeHandle mt = GetTypeHandle(mtAddr); + ITypeHandle mt = GetTypeHandle(mtAddr); return GetLoaderModule(mt); } } - private TargetPointer GetLoaderModule(TypeHandle typeHandle) + private TargetPointer GetLoaderModule(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) { @@ -2038,7 +2043,7 @@ Getting the native code pointer for methods with a NativeCodeSlot or a stable en } TargetPointer methodTablePointer = md.MethodTable; - TypeHandle typeHandle = GetTypeHandle(methodTablePointer); + ITypeHandle typeHandle = GetTypeHandle(methodTablePointer); TargetPointer addrOfSlot = GetAddressOfSlot(typeHandle, md.Slot); return _target.ReadCodePointer(addrOfSlot); } @@ -2050,7 +2055,7 @@ Getting the native code pointer for methods with a NativeCodeSlot or a stable en return methodDescPointer.Value + offset; } - private TargetPointer GetAddressOfSlot(TypeHandle typeHandle, uint slotNum) + private TargetPointer GetAddressOfSlot(ITypeHandle typeHandle, uint slotNum) { if (!typeHandle.IsMethodTable()) throw new InvalidOperationException("typeHandle is not a MethodTable"); @@ -2104,7 +2109,7 @@ Getting the native code pointer for methods with a NativeCodeSlot or a stable en Getting the value of a slot of a MethodTable ```csharp - public TargetCodePointer GetSlot(TypeHandle typeHandle, uint slot) + public TargetCodePointer GetSlot(ITypeHandle typeHandle, uint slot) { // based on MethodTable::GetSlot(uint slotNumber) if (!typeHandle.IsMethodTable()) @@ -2123,7 +2128,7 @@ Getting the value of a slot of a MethodTable Getting a MethodDesc for a certain slot in a MethodTable ```csharp // Based on MethodTable::IntroducedMethodIterator - private IEnumerable GetIntroducedMethods(TypeHandle typeHandle) + private IEnumerable GetIntroducedMethods(ITypeHandle typeHandle) { // typeHandle must represent a MethodTable @@ -2169,12 +2174,12 @@ Getting a MethodDesc for a certain slot in a MethodTable } } - public IEnumerable GetIntroducedMethodDescs(TypeHandle typeHandle) + public IEnumerable GetIntroducedMethodDescs(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) throw new ArgumentException($"{nameof(typeHandle)} is not a MethodTable"); - TypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); + ITypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); foreach (MethodDescHandle mdh in GetIntroducedMethods(canonMT)) { yield return mdh.Address; @@ -2183,12 +2188,12 @@ Getting a MethodDesc for a certain slot in a MethodTable // Uses GetMethodDescForVtableSlot if slot is less than the number of vtable slots // otherwise looks for the slot in the introduced methods - public TargetPointer GetMethodDescForSlot(TypeHandle typeHandle, ushort slot) + public TargetPointer GetMethodDescForSlot(ITypeHandle typeHandle, ushort slot) { if (!typeHandle.IsMethodTable()) throw new ArgumentException($"{nameof(typeHandle)} is not a MethodTable"); - TypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); + ITypeHandle canonMT = GetTypeHandle(GetCanonicalMethodTable(typeHandle)); if (slot < GetNumVtableSlots(canonMT)) { return GetMethodDescForVtableSlot(canonMT, slot); @@ -2207,14 +2212,14 @@ Getting a MethodDesc for a certain slot in a MethodTable } } - private TargetPointer GetMethodDescForVtableSlot(TypeHandle methodTable, ushort slot) + private TargetPointer GetMethodDescForVtableSlot(ITypeHandle methodTable, ushort slot) { // based on MethodTable::GetMethodDescForSlot_NoThrow if (!typeHandle.IsMethodTable()) throw new ArgumentException($"{nameof(typeHandle)} is not a MethodTable"); TargetPointer cannonMTPTr = GetCanonicalMethodTable(typeHandle); - TypeHandle canonMT = GetTypeHandle(cannonMTPTr); + ITypeHandle canonMT = GetTypeHandle(cannonMTPTr); if (slot >= GetNumVtableSlots(canonMT)) throw new ArgumentException(nameof(slot), "Slot number is greater than the number of slots"); @@ -2227,7 +2232,7 @@ Getting a MethodDesc for a certain slot in a MethodTable while (lookupMTPtr != TargetPointer.Null) { // if pCode is null, we iterate through the method descs in the MT. - TypeHandle lookupMT = GetTypeHandle(lookupMTPtr); + ITypeHandle lookupMT = GetTypeHandle(lookupMTPtr); foreach (MethodDescHandle mdh in GetIntroducedMethods(lookupMT)) { MethodDesc md = _methodDescs[mdh.Address]; @@ -2345,7 +2350,7 @@ TargetPointer GetFieldDescThreadStaticAddress(TargetPointer fieldDescPointer, Ta // The unboxValueTypes parameter behaves the same as in GetFieldDescStaticAddress. } -TypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) +ITypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) { // Resolve enclosing MT -> Module -> MetadataReader, decode the field's // signature using the SignatureDecoder contract with a SignatureTypeProvider @@ -2384,7 +2389,7 @@ void GetCoreLibFieldDescAndDef(string @namespace, string typeName, string fieldN TargetPointer systemAssembly = loader.GetSystemAssembly(); ModuleHandle moduleHandle = loader.GetModuleHandleFromAssemblyPtr(systemAssembly); IRuntimeTypeSystem rts = (IRuntimeTypeSystem)this; - TypeHandle th = rts.GetTypeByNameAndModule(typeName, @namespace, moduleHandle); + ITypeHandle th = rts.GetTypeByNameAndModule(typeName, @namespace, moduleHandle); fieldDescAddr = rts.GetFieldDescByName(th, fieldName); uint token = rts.GetFieldDescMemberDef(fieldDescAddr); FieldDefinitionHandle fieldHandle = (FieldDefinitionHandle)MetadataTokens.Handle((int)token); diff --git a/docs/design/datacontracts/Signature.md b/docs/design/datacontracts/Signature.md index 1af22ad18e4dc1..a43211b29d7e58 100644 --- a/docs/design/datacontracts/Signature.md +++ b/docs/design/datacontracts/Signature.md @@ -8,15 +8,15 @@ The runtime extends the standard ECMA-335 element type encoding with values that | Encoding | Value | Layout following the tag | | --- | --- | --- | -| `ELEMENT_TYPE_INTERNAL` | `0x21` | a target-sized pointer to a runtime `TypeHandle` | -| `ELEMENT_TYPE_CMOD_INTERNAL` | `0x22` | one byte (`1` = required, `0` = optional), then a target-sized pointer to a runtime `TypeHandle` | +| `ELEMENT_TYPE_INTERNAL` | `0x21` | a target-sized pointer to a runtime `ITypeHandle` | +| `ELEMENT_TYPE_CMOD_INTERNAL` | `0x22` | one byte (`1` = required, `0` = optional), then a target-sized pointer to a runtime `ITypeHandle` | These tags are used in signatures generated internally by the runtime that are not persisted to a managed image. They are defined alongside the standard ECMA-335 element types in `src/coreclr/inc/corhdr.h`. Their literal values are part of this contract -- changing them is a breaking change. ## APIs of contract ```csharp -TypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, TypeHandle ctx); +ITypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx); // Returns the address of the first argument of a vararg call relative to the cookie pointer location. TargetPointer GetVarArgArgsBase(TargetPointer vaSigCookieAddr); @@ -51,10 +51,10 @@ Contracts used: Constants: | Constant Name | Meaning | Value | | --- | --- | --- | -| `ELEMENT_TYPE_INTERNAL` | runtime-internal element type tag for an internal `TypeHandle` | `0x21` | +| `ELEMENT_TYPE_INTERNAL` | runtime-internal element type tag for an internal `ITypeHandle` | `0x21` | | `ELEMENT_TYPE_CMOD_INTERNAL` | runtime-internal element type tag for an internal modified type | `0x22` | -Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a runtime `TypeHandle`. +Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a runtime `ITypeHandle`. The decoder is implemented as `RuntimeSignatureDecoder` -- a clone of SRM's `SignatureDecoder` with added support for the runtime-internal element types. The clone takes an additional `Target` so internal-type pointers can be sized for the target architecture. Provider implementations implement `IRuntimeSignatureTypeProvider` -- a superset of `System.Reflection.Metadata.ISignatureTypeProvider` -- adding methods for the runtime-internal element types: @@ -63,15 +63,15 @@ TType GetInternalType(TargetPointer typeHandlePointer); TType GetInternalModifiedType(TargetPointer typeHandlePointer, TType unmodifiedType, bool isRequired); ``` -The contract's provider resolves these pointers through `RuntimeTypeSystem.GetTypeHandle`. Standard ECMA-335 element types resolve through `RuntimeTypeSystem.GetPrimitiveType` and `RuntimeTypeSystem.GetConstructedType`. Generic type parameters (`VAR`) and generic method parameters (`MVAR`) resolve via `RuntimeTypeSystem.GetInstantiation` and `RuntimeTypeSystem.GetGenericMethodInstantiation` respectively, using a `TypeHandle` (for generic types) or `MethodDescHandle` (for generic methods) generic context. `GetTypeFromDefinition` and `GetTypeFromReference` resolve tokens via the module's `TypeDefToMethodTableMap` / `TypeRefToMethodTableMap`; cross-module references and `GetTypeFromSpecification` are not currently implemented. +The contract's provider resolves these pointers through `RuntimeTypeSystem.GetTypeHandle`. Standard ECMA-335 element types resolve through `RuntimeTypeSystem.GetPrimitiveType` and `RuntimeTypeSystem.GetConstructedType`. Generic type parameters (`VAR`) and generic method parameters (`MVAR`) resolve via `RuntimeTypeSystem.GetInstantiation` and `RuntimeTypeSystem.GetGenericMethodInstantiation` respectively, using a `ITypeHandle` (for generic types) or `MethodDescHandle` (for generic methods) generic context. `GetTypeFromDefinition` and `GetTypeFromReference` resolve tokens via the module's `TypeDefToMethodTableMap` / `TypeRefToMethodTableMap`; cross-module references and `GetTypeFromSpecification` are not currently implemented. ```csharp -TypeHandle ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, TypeHandle ctx) +ITypeHandle ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) { - SignatureTypeProvider provider = new(_target, moduleHandle); + SignatureTypeProvider provider = new(_target, moduleHandle); MetadataReader mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle)!; BlobReader blobReader = mdReader.GetBlobReader(blobHandle); - RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); + RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); return decoder.DecodeFieldSignature(ref blobReader); } ``` diff --git a/src/native/managed/cdac/IData.md b/src/native/managed/cdac/IData.md index d0538d2bea5757..b6f92aa38575a6 100644 --- a/src/native/managed/cdac/IData.md +++ b/src/native/managed/cdac/IData.md @@ -60,7 +60,7 @@ analyzer. It scans for classes carrying `[CdacType]` and emits a * A `private static readonly string[] _typeNames = { ... }` array holding the candidate type names from `[CdacType]`. * For types with `HasTypeHandle = true`: a - `public static TypeHandle TypeHandle(Target target)` accessor. + `public static ITypeHandle TypeHandle(Target target)` accessor. * For each `[Field(Writable = true)]` property: a `public void Write{Name}(T value)` method. The class captures the `Target` in a private `_target` field when any writable fields exist. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs index 937ee347a0d132..843d96a31f4792 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs @@ -144,7 +144,7 @@ public List GetMOWs(TargetPointer obj, out bool hasMOWTable) public bool IsComWrappersRCW(TargetPointer rcw) { TargetPointer mt = _target.Contracts.Object.GetMethodTableAddress(rcw); - return mt == Data.NativeObjectWrapper.ITypeHandle(_target).Address; + return mt == Data.NativeObjectWrapper.TypeHandle(_target).Address; } public TargetPointer GetComWrappersRCWForObject(TargetPointer obj) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs index 65b84c55b8b06b..14a818df4d788f 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs @@ -19,7 +19,7 @@ public TargetTypeHandle(TargetPointer address) public bool IsNull => Address == 0; public bool Equals(ITypeHandle? other) - => other is TargetTypeHandle t && Address == t.Address; + => other is not null && Address == other.Address; public bool Equals(TargetTypeHandle? other) => other is not null && Address == other.Address; public override bool Equals(object? obj) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs index 9bbde3b0e4b0dc..4c8138c6685497 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; diff --git a/src/native/managed/cdac/gen/Emitter.cs b/src/native/managed/cdac/gen/Emitter.cs index 3d3e054d901310..25a85d5ed91f9b 100644 --- a/src/native/managed/cdac/gen/Emitter.cs +++ b/src/native/managed/cdac/gen/Emitter.cs @@ -62,7 +62,7 @@ public static string Emit(CdacTypeModel model) // The class advertises a managed identity (ITypeHandle) when HasTypeHandle is set. if (model.HasTypeHandle) { - sb.AppendLine($" public static {ITypeHandleType} ITypeHandle({Target} target)"); + sb.AppendLine($" public static {ITypeHandleType} TypeHandle({Target} target)"); sb.AppendLine($" => TypeNameResolver.GetTypeHandle(target, _typeNames);"); sb.AppendLine(); } diff --git a/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs index c11036738231ee..2dec061edbe3d8 100644 --- a/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs @@ -94,7 +94,7 @@ public void CCW_InterfaceMethodTablesAreReadable(TestConfiguration config) if (iface.MethodTable == TargetPointer.Null) continue; - // Verify the MethodTable is readable by resolving it to a ITypeHandle. + // Verify the MethodTable is readable by resolving it to an ITypeHandle. ITypeHandle typeHandle = rts.GetTypeHandle(iface.MethodTable); Assert.False(typeHandle.IsNull, $"Expected non-null ITypeHandle for MethodTable 0x{iface.MethodTable:X} in CCW 0x{ccwPtr:X}"); From c167ba629462c4230cb8840eaf60f0545947b2ec Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 16:01:46 -0400 Subject: [PATCH 04/23] Intern TargetTypeHandle instances per address in GetTypeHandle GetTypeHandle is a hot entrypoint (signature decoding, object/type inspection). Since TargetTypeHandle is now a reference type, returning a new instance on every call allocates. Cache handles per address in a _targetTypeHandles dictionary (cleared on Flush alongside the other per-target caches) so repeated lookups reuse the same instance. Addresses PR review feedback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../Contracts/RuntimeTypeSystem_1.cs | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index d76a3b0c5edd74..c53badc51ee5a6 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -32,12 +32,27 @@ internal partial struct RuntimeTypeSystem_1 : IRuntimeTypeSystem private readonly Dictionary _methodTables = new(); private readonly Dictionary _methodDescs = new(); private readonly Dictionary _typeHandles = new(); + // Interns TargetTypeHandle instances per address so repeated GetTypeHandle calls + // (a hot entrypoint for signature decoding, object/type inspection, etc.) don't + // allocate a new handle each time. + private readonly Dictionary _targetTypeHandles = new(); public void Flush(FlushScope scope) { _methodTables.Clear(); _methodDescs.Clear(); _typeHandles.Clear(); + _targetTypeHandles.Clear(); + } + + private TargetTypeHandle GetOrCreateTargetTypeHandle(TargetPointer address) + { + if (!_targetTypeHandles.TryGetValue(address, out TargetTypeHandle? handle)) + { + handle = new TargetTypeHandle(address); + _targetTypeHandles[address] = handle; + } + return handle; } internal struct MethodTable @@ -477,14 +492,14 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) // if we already validated this address, return a handle if (_methodTables.ContainsKey(typeHandlePointer)) { - return new TargetTypeHandle(typeHandlePointer); + return GetOrCreateTargetTypeHandle(typeHandlePointer); } // Check for a TypeDesc if (addressLowBits == TypeHandleBits.TypeDesc) { // This is a TypeDesc - return new TargetTypeHandle(typeHandlePointer); + return GetOrCreateTargetTypeHandle(typeHandlePointer); } TargetPointer methodTablePointer = typeHandlePointer; @@ -495,7 +510,7 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) // we already cached the data, we must have validated the address, create the representation struct for our use MethodTable trustedMethodTable = new MethodTable(methodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTable); - return new TargetTypeHandle(methodTablePointer); + return GetOrCreateTargetTypeHandle(methodTablePointer); } // If it's the free object method table, we trust it to be valid @@ -504,7 +519,7 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) Data.MethodTable freeObjectMethodTableData = _target.ProcessedData.GetOrAdd(methodTablePointer); MethodTable trustedMethodTable = new MethodTable(freeObjectMethodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTable); - return new TargetTypeHandle(methodTablePointer); + return GetOrCreateTargetTypeHandle(methodTablePointer); } // Otherwse, get ready to validate @@ -516,7 +531,7 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) Data.MethodTable trustedMethodTableData = _target.ProcessedData.GetOrAdd(methodTablePointer); MethodTable trustedMethodTableF = new MethodTable(trustedMethodTableData); _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTableF); - return new TargetTypeHandle(methodTablePointer); + return GetOrCreateTargetTypeHandle(methodTablePointer); } public TargetPointer GetModule(ITypeHandle typeHandle) { From ef3c912e42a95efd77e8ac0d60d3b59181669eff Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 16:21:20 -0400 Subject: [PATCH 05/23] Use an expression-bodied static property for ITypeHandle.Null Prefer static ITypeHandle Null => NullTypeHandle.Instance; over a static auto-property with initializer on the interface. Addresses PR review feedback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../Contracts/IRuntimeTypeSystem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index da7b0722e85d28..9c8cdb4f254c85 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -16,7 +16,9 @@ public interface ITypeHandle : IEquatable { TargetPointer Address { get; } bool IsNull { get; } - static ITypeHandle Null { get; } = NullTypeHandle.Instance; + + /// Sentinel handle representing the absence of a type. + static ITypeHandle Null => NullTypeHandle.Instance; } /// From 8bd863c027c95f815c755d1e6f3ff0059e18eb33 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 17:04:30 -0400 Subject: [PATCH 06/23] Use canonical reference identity for ITypeHandle Treat ITypeHandle as an opaque canonical identity owned by the RuntimeTypeSystem rather than requiring every implementation to coordinate cross-implementation value equality. - Remove IEquatable and concrete Equals/GetHashCode overrides. - Make TargetTypeHandle internal so consumers cannot fabricate noncanonical instances. - Use reference identity (including identity hash codes) in the constructed type cache key. - Update the one mock that relied on equivalent-but-distinct handle objects. - Add coverage that repeated GetTypeHandle calls return the same instance. - Document the RTS-owned canonical identity contract. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- docs/design/datacontracts/RuntimeTypeSystem.md | 7 ++++--- .../Contracts/IRuntimeTypeSystem.cs | 5 +---- .../TypeHandleImplementations.cs | 17 ++++------------- .../Contracts/RuntimeTypeSystem_1.cs | 9 +++++---- .../cdac/tests/UnitTests/DacDbiImplTests.cs | 10 ++++++---- .../cdac/tests/UnitTests/MethodTableTests.cs | 16 ++++++++++++++++ 6 files changed, 36 insertions(+), 28 deletions(-) diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index 2c425ef16077ab..2e187fc36beb5b 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -10,8 +10,9 @@ An `ITypeHandle` is the runtime representation of the type information about a v Given a `TargetPointer` address, the `RuntimeTypeSystem` contract provides an `ITypeHandle` for querying the details of the type. ``` csharp -// An opaque handle to a runtime type, backed by a target-process MethodTable or TypeDesc address. -interface ITypeHandle : IEquatable +// An opaque canonical identity for a runtime type. Handles are produced and +// interned by RuntimeTypeSystem; consumers must not fabricate implementations. +interface ITypeHandle { TargetPointer Address { get; } bool IsNull { get; } @@ -20,7 +21,7 @@ interface ITypeHandle : IEquatable static ITypeHandle Null { get; } } -// A real target-backed handle (a MethodTable* or TypeDesc* address). +// An internal real target-backed handle (a MethodTable* or TypeDesc* address). class TargetTypeHandle : ITypeHandle { /* ... */ } readonly record struct TypedByRefInfo(TargetPointer Data, TargetPointer TypeHandle); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index 9c8cdb4f254c85..868a795932d8ef 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -12,7 +12,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; /// An opaque handle to a runtime type, backed by a target-process MethodTable or /// TypeDesc address. /// -public interface ITypeHandle : IEquatable +public interface ITypeHandle { TargetPointer Address { get; } bool IsNull { get; } @@ -31,9 +31,6 @@ internal sealed class NullTypeHandle : ITypeHandle private NullTypeHandle() { } public TargetPointer Address => TargetPointer.Null; public bool IsNull => true; - public bool Equals(ITypeHandle? other) => other is not null && other.IsNull; - public override bool Equals(object? obj) => obj is ITypeHandle th && Equals(th); - public override int GetHashCode() => 0; } public enum CorElementType diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs index 14a818df4d788f..9022da7ecc8f14 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs @@ -1,28 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; - namespace Microsoft.Diagnostics.DataContractReader.Contracts; /// -/// An ITypeHandle backed by a real target-process address (MethodTable* or TypeDesc*). +/// A canonical ITypeHandle backed by a real target-process address +/// (MethodTable* or TypeDesc*). /// -public sealed class TargetTypeHandle : ITypeHandle, IEquatable +internal sealed class TargetTypeHandle : ITypeHandle { - public TargetTypeHandle(TargetPointer address) + internal TargetTypeHandle(TargetPointer address) { Address = address; } public TargetPointer Address { get; } public bool IsNull => Address == 0; - - public bool Equals(ITypeHandle? other) - => other is not null && Address == other.Address; - public bool Equals(TargetTypeHandle? other) - => other is not null && Address == other.Address; - public override bool Equals(object? obj) - => obj is ITypeHandle th && Equals(th); - public override int GetHashCode() => Address.GetHashCode(); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index c53badc51ee5a6..3d947c75eb6a57 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata.Ecma335; +using System.Runtime.CompilerServices; using Microsoft.Diagnostics.DataContractReader.RuntimeTypeSystemHelpers; using Microsoft.Diagnostics.DataContractReader.Data; using System.Reflection.Metadata; @@ -104,11 +105,11 @@ public TypeKey(ITypeHandle typeHandle, CorElementType elementType, int rank, Imm public bool Equals(TypeKey other) { - if (ElementType != other.ElementType || Rank != other.Rank || CallConv != other.CallConv || TypeArgs.Length != other.TypeArgs.Length || !TypeHandle.Equals(other.TypeHandle)) + if (ElementType != other.ElementType || Rank != other.Rank || CallConv != other.CallConv || TypeArgs.Length != other.TypeArgs.Length || !ReferenceEquals(TypeHandle, other.TypeHandle)) return false; for (int i = 0; i < TypeArgs.Length; i++) { - if (!TypeArgs[i].Equals(other.TypeArgs[i])) + if (!ReferenceEquals(TypeArgs[i], other.TypeArgs[i])) return false; } return true; @@ -118,10 +119,10 @@ public bool Equals(TypeKey other) public override int GetHashCode() { - int hash = HashCode.Combine(TypeHandle.GetHashCode(), (int)ElementType, Rank, (int)CallConv); + int hash = HashCode.Combine(RuntimeHelpers.GetHashCode(TypeHandle), (int)ElementType, Rank, (int)CallConv); foreach (ITypeHandle th in TypeArgs) { - hash = HashCode.Combine(hash, th.GetHashCode()); + hash = HashCode.Combine(hash, RuntimeHelpers.GetHashCode(th)); } return hash; } diff --git a/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs b/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs index 7a45d04cfa79e8..ab85a54c569667 100644 --- a/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs @@ -339,8 +339,9 @@ public void IsExceptionObject(MockTarget.Architecture arch, int inheritanceDepth mockRts.Setup(r => r.GetWellKnownMethodTable(WellKnownMethodTable.Exception)).Returns(exceptionMT); if (intermediateMTs.Length == 0 && !isException) { - mockRts.Setup(r => r.GetTypeHandle(objectMT)).Returns(new TargetTypeHandle(objectMT)); - mockRts.Setup(r => r.GetParentMethodTable(new TargetTypeHandle(objectMT))).Returns(TargetPointer.Null); + ITypeHandle objectTypeHandle = new TargetTypeHandle(objectMT); + mockRts.Setup(r => r.GetTypeHandle(objectMT)).Returns(objectTypeHandle); + mockRts.Setup(r => r.GetParentMethodTable(objectTypeHandle)).Returns(TargetPointer.Null); } for (int i = 0; i < intermediateMTs.Length; i++) { @@ -349,8 +350,9 @@ public void IsExceptionObject(MockTarget.Architecture arch, int inheritanceDepth ? intermediateMTs[i + 1] : isException ? exceptionMT : TargetPointer.Null; - mockRts.Setup(r => r.GetTypeHandle(current)).Returns(new TargetTypeHandle(current)); - mockRts.Setup(r => r.GetParentMethodTable(new TargetTypeHandle(current))).Returns(parent); + ITypeHandle currentTypeHandle = new TargetTypeHandle(current); + mockRts.Setup(r => r.GetTypeHandle(current)).Returns(currentTypeHandle); + mockRts.Setup(r => r.GetParentMethodTable(currentTypeHandle)).Returns(parent); } var (dacDbi, _) = CreateDacDbiWithExceptionMT(arch, mockObject, mockRts); diff --git a/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs b/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs index 22da592b6b455a..48d181a851ca55 100644 --- a/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs @@ -89,6 +89,22 @@ public void HasRuntimeTypeSystemContract(MockTarget.Architecture arch) Assert.False(contract.IsObject(handle)); } + [Theory] + [ClassData(typeof(MockTarget.StdArch))] + public void GetTypeHandleReturnsCanonicalInstance(MockTarget.Architecture arch) + { + TargetPointer freeObjectMethodTableAddress = default; + TestPlaceholderTarget target = CreateTarget( + arch, + builder => freeObjectMethodTableAddress = builder.FreeObjectMethodTableAddress); + + IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; + ITypeHandle first = contract.GetTypeHandle(freeObjectMethodTableAddress); + ITypeHandle second = contract.GetTypeHandle(freeObjectMethodTableAddress); + + Assert.Same(first, second); + } + [Theory] [ClassData(typeof(MockTarget.StdArch))] public void ValidateSystemObjectMethodTable(MockTarget.Architecture arch) From cfa662b65d1a8f6a1d92c6f999c1cb4599bc552f Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 21:26:20 -0400 Subject: [PATCH 07/23] Address remaining PR review feedback - Fix "a ITypeHandle" grammar in TypeDataWalk. - Update the RuntimeTypeSystem contract example to return the canonical target handle through GetOrCreateTargetTypeHandle. - Rename the new GetFieldDescListLayout parameter type added on main to ITypeHandle after rebasing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- docs/design/datacontracts/RuntimeTypeSystem.md | 2 +- .../Contracts/RuntimeTypeSystem_1.cs | 2 +- .../Dbi/TypeDataWalk.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index 2e187fc36beb5b..7302d735c13e17 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -615,7 +615,7 @@ Contracts used: ... // If this is a MethodTable ... // read Data.MethodTable from typeHandlePointer. ... // create a MethodTable_1 and add it to _methodTables. - return TypeHandle { Address = typeHandlePointer } + return GetOrCreateTargetTypeHandle(typeHandlePointer); } public TargetPointer GetModule(ITypeHandle TypeHandle) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index 3d947c75eb6a57..e5c9ac23dc6fa8 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -929,7 +929,7 @@ public IEnumerable GetFieldDescList(ITypeHandle typeHandle) // Returns the start pointer, per-element size, and count of the enclosing type's contiguous FieldDesc // array (the fields declared by the type: its own instance fields plus its static fields). - private (TargetPointer ListStart, uint FieldDescSize, int TotalFields) GetFieldDescListLayout(TypeHandle typeHandle) + private (TargetPointer ListStart, uint FieldDescSize, int TotalFields) GetFieldDescListLayout(ITypeHandle typeHandle) { TargetPointer fieldDescListPtr = GetClassData(typeHandle).FieldDescList; uint fieldDescSize = _target.GetTypeInfo(DataType.FieldDesc).Size!.Value; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs index 410b629413e748..ec7e2e21377cc1 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs @@ -11,7 +11,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Legacy; // Port of native DacDbiInterfaceImpl::TypeDataWalk // // Walks the flattened DebuggerIPCE_TypeArgData[] tree that the right side built in -// CordbType::GatherTypeData and produces a ITypeHandle for the loaded representation +// CordbType::GatherTypeData and produces an ITypeHandle for the loaded representation // (exact, or canonical when generic code-sharing collapses reference type-args to // System.__Canon and value type-args to their canonical form). // From 5650fcc5e72b9aebd285bbb86a009b5bc22db4ef Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 21:43:00 -0400 Subject: [PATCH 08/23] Clarify runtime TypeHandle terminology and simplify ITypeHandle usage - Describe ELEMENT_TYPE_INTERNAL payloads as native runtime TypeHandles, which are resolved to cDAC ITypeHandles by the reader. - Restore native VMPTR_TypeHandle names in the DacDbi wire-layout comments. - Use explicit ImmutableArray locals instead of var. - Remove redundant Contracts. qualifiers where the Contracts namespace is already imported. - Fix remaining "a ITypeHandle" grammar. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- docs/design/datacontracts/Signature.md | 10 ++--- .../ClrDataFrame.cs | 2 +- .../Dbi/DacDbiImpl.cs | 10 ++--- .../Dbi/IDacDbiInterface.cs | 6 +-- .../SOSDacImpl.IXCLRDataProcess.cs | 4 +- .../SOSDacImpl.cs | 18 ++++----- .../SigFormat.cs | 2 +- .../TypeNameBuilder.cs | 14 +++---- .../cdac/tests/UnitTests/MethodTableTests.cs | 40 +++++++++---------- 9 files changed, 53 insertions(+), 53 deletions(-) diff --git a/docs/design/datacontracts/Signature.md b/docs/design/datacontracts/Signature.md index a43211b29d7e58..72507f4b6074c5 100644 --- a/docs/design/datacontracts/Signature.md +++ b/docs/design/datacontracts/Signature.md @@ -8,8 +8,8 @@ The runtime extends the standard ECMA-335 element type encoding with values that | Encoding | Value | Layout following the tag | | --- | --- | --- | -| `ELEMENT_TYPE_INTERNAL` | `0x21` | a target-sized pointer to a runtime `ITypeHandle` | -| `ELEMENT_TYPE_CMOD_INTERNAL` | `0x22` | one byte (`1` = required, `0` = optional), then a target-sized pointer to a runtime `ITypeHandle` | +| `ELEMENT_TYPE_INTERNAL` | `0x21` | a target-sized pointer to a runtime `TypeHandle` | +| `ELEMENT_TYPE_CMOD_INTERNAL` | `0x22` | one byte (`1` = required, `0` = optional), then a target-sized pointer to a runtime `TypeHandle` | These tags are used in signatures generated internally by the runtime that are not persisted to a managed image. They are defined alongside the standard ECMA-335 element types in `src/coreclr/inc/corhdr.h`. Their literal values are part of this contract -- changing them is a breaking change. @@ -51,10 +51,10 @@ Contracts used: Constants: | Constant Name | Meaning | Value | | --- | --- | --- | -| `ELEMENT_TYPE_INTERNAL` | runtime-internal element type tag for an internal `ITypeHandle` | `0x21` | +| `ELEMENT_TYPE_INTERNAL` | runtime-internal element type tag for an internal `TypeHandle` | `0x21` | | `ELEMENT_TYPE_CMOD_INTERNAL` | runtime-internal element type tag for an internal modified type | `0x22` | -Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a runtime `ITypeHandle`. +Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer to a runtime `TypeHandle` (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a cDAC `ITypeHandle`. The decoder is implemented as `RuntimeSignatureDecoder` -- a clone of SRM's `SignatureDecoder` with added support for the runtime-internal element types. The clone takes an additional `Target` so internal-type pointers can be sized for the target architecture. Provider implementations implement `IRuntimeSignatureTypeProvider` -- a superset of `System.Reflection.Metadata.ISignatureTypeProvider` -- adding methods for the runtime-internal element types: @@ -63,7 +63,7 @@ TType GetInternalType(TargetPointer typeHandlePointer); TType GetInternalModifiedType(TargetPointer typeHandlePointer, TType unmodifiedType, bool isRequired); ``` -The contract's provider resolves these pointers through `RuntimeTypeSystem.GetTypeHandle`. Standard ECMA-335 element types resolve through `RuntimeTypeSystem.GetPrimitiveType` and `RuntimeTypeSystem.GetConstructedType`. Generic type parameters (`VAR`) and generic method parameters (`MVAR`) resolve via `RuntimeTypeSystem.GetInstantiation` and `RuntimeTypeSystem.GetGenericMethodInstantiation` respectively, using a `ITypeHandle` (for generic types) or `MethodDescHandle` (for generic methods) generic context. `GetTypeFromDefinition` and `GetTypeFromReference` resolve tokens via the module's `TypeDefToMethodTableMap` / `TypeRefToMethodTableMap`; cross-module references and `GetTypeFromSpecification` are not currently implemented. +The contract's provider resolves these pointers through `RuntimeTypeSystem.GetTypeHandle`. Standard ECMA-335 element types resolve through `RuntimeTypeSystem.GetPrimitiveType` and `RuntimeTypeSystem.GetConstructedType`. Generic type parameters (`VAR`) and generic method parameters (`MVAR`) resolve via `RuntimeTypeSystem.GetInstantiation` and `RuntimeTypeSystem.GetGenericMethodInstantiation` respectively, using an `ITypeHandle` (for generic types) or `MethodDescHandle` (for generic methods) generic context. `GetTypeFromDefinition` and `GetTypeFromReference` resolve tokens via the module's `TypeDefToMethodTableMap` / `TypeRefToMethodTableMap`; cross-module references and `GetTypeFromSpecification` are not currently implemented. ```csharp ITypeHandle ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs index ebb83d632e1ea6..f14cb0d2360f3d 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs @@ -755,7 +755,7 @@ public FlagSignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHan IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = rts.GetMethodTable(mdh); ITypeHandle declaringType = rts.GetTypeHandle(mtAddr); - var typeInst = rts.GetInstantiation(declaringType); + ImmutableArray typeInst = rts.GetInstantiation(declaringType); return ResolveGenericParam(rts, typeInst[index]); } catch (System.Exception) { return ((uint)ClrDataValueFlag.DEFAULT, -1); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs index 4f1ad05fc48b07..e04206b76d90dd 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs @@ -251,7 +251,7 @@ public int ResolveTypeReference(DacDbiTypeRefData* pTypeRefInfo, DacDbiTypeRefDa if (methodTable != TargetPointer.Null) { Contracts.IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = rts.GetTypeHandle(methodTable); + ITypeHandle typeHandle = rts.GetTypeHandle(methodTable); TargetPointer typeDefModulePtr = rts.GetModule(typeHandle); Contracts.ModuleHandle typeDefModule = loader.GetModuleHandleFromModulePtr(typeDefModulePtr); targetAssembly = loader.GetAssembly(typeDefModule); @@ -2239,7 +2239,7 @@ public int RequiresAlign8(ulong thExact, Interop.BOOL* pResult) if (arch == RuntimeInfoArchitecture.Arm || arch == RuntimeInfoArchitecture.Wasm) { Contracts.IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle th = rts.GetTypeHandle(new TargetPointer(thExact)); + ITypeHandle th = rts.GetTypeHandle(new TargetPointer(thExact)); *pResult = rts.RequiresAlign8(th) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; } else @@ -2397,7 +2397,7 @@ public int IsValueType(ulong vmTypeHandle, Interop.BOOL* pResult) try { Contracts.IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle th = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); + ITypeHandle th = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); *pResult = rts.IsValueType(th) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; } catch (System.Exception ex) @@ -3474,7 +3474,7 @@ public int GetSimpleType(int simpleType, uint* pMetadataToken, ulong* pVmModule) try { Contracts.IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = rts.GetPrimitiveType((CorElementType)simpleType); + ITypeHandle typeHandle = rts.GetPrimitiveType((CorElementType)simpleType); if (typeHandle.IsNull) { @@ -5938,7 +5938,7 @@ private void FillFnPtrTypeInfo(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, // Fills a DebuggerIPCE_BasicTypeData for a type handle — used for array element types // and ptr/byref referent types. Exposed as internal so tests can build the ArgInfoList - // needed to round-trip a ITypeHandle through GetExactTypeHandle. + // needed to round-trip an ITypeHandle through GetExactTypeHandle. internal void FillBasicTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, out DebuggerIPCE_BasicTypeData typeInfo) { typeInfo = default; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs index a330454eb368d6..cc96dd9fc20abd 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs @@ -375,7 +375,7 @@ public struct DebuggerIPCE_BasicTypeData [FieldOffset(0)] public int elementType; // Portable [FieldOffset(4)] public uint metadataToken; // Portable [FieldOffset(8)] public ulong vmAssembly; // VMPTR_Assembly (Portable) - [FieldOffset(16)] public ulong vmTypeHandle; // VMPTR_ITypeHandle (Portable) + [FieldOffset(16)] public ulong vmTypeHandle; // VMPTR_TypeHandle (Portable) } [StructLayout(LayoutKind.Sequential)] @@ -398,7 +398,7 @@ public struct DebuggerIPCE_ExpandedTypeData // ClassTypeData (used for E_T_CLASS, E_T_VALUETYPE) [FieldOffset(8)] public uint ClassTypeData_metadataToken; // Portable [FieldOffset(16)] public ulong ClassTypeData_vmAssembly; // VMPTR_Assembly - [FieldOffset(24)] public ulong ClassTypeData_typeHandle; // VMPTR_ITypeHandle + [FieldOffset(24)] public ulong ClassTypeData_typeHandle; // VMPTR_TypeHandle // UnaryTypeData (used for E_T_PTR, E_T_BYREF) — overlaps union at offset 8 [FieldOffset(8)] public DebuggerIPCE_BasicTypeData UnaryTypeData_unaryTypeArg; @@ -408,7 +408,7 @@ public struct DebuggerIPCE_ExpandedTypeData [FieldOffset(32)] public uint ArrayTypeData_arrayRank; // Portable // NaryTypeData (used for E_T_FNPTR) — overlaps union at offset 8 - [FieldOffset(8)] public ulong NaryTypeData_typeHandle; // VMPTR_ITypeHandle + [FieldOffset(8)] public ulong NaryTypeData_typeHandle; // VMPTR_TypeHandle } [StructLayout(LayoutKind.Sequential)] diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs index 27f054e9dc48f2..5a2e416b785e47 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs @@ -298,7 +298,7 @@ private IEnumerable IterateMethodInstantiations(Contracts.Modu } } - private IEnumerable IterateTypeParams(Contracts.ModuleHandle moduleHandle) + private IEnumerable IterateTypeParams(Contracts.ModuleHandle moduleHandle) { IEnumerable typeParams = _loader.GetAvailableTypeParams(moduleHandle); @@ -382,7 +382,7 @@ 4. Generic method on Generic type (There are N generic defining methods where N { if (HasClassInstantiation(mainMD)) { - foreach (Contracts.ITypeHandle typeParam in IterateTypeParams(moduleHandle)) + foreach (ITypeHandle typeParam in IterateTypeParams(moduleHandle)) { uint typeParamToken = _rts.GetTypeDefToken(typeParam); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs index af7656416b35f5..6aa86a9b85c7f2 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs @@ -2793,7 +2793,7 @@ int ISOSDacInterface.GetMethodTableData(ClrDataAddress mt, DacpMethodTableData* if (mt == 0 || data == null) throw new ArgumentException(); Contracts.IRuntimeTypeSystem contract = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle methodTable = contract.GetTypeHandle(mt.ToTargetPointer(_target)); + ITypeHandle methodTable = contract.GetTypeHandle(mt.ToTargetPointer(_target)); DacpMethodTableData result = default; result.baseSize = contract.GetBaseSize(methodTable); @@ -2906,7 +2906,7 @@ int ISOSDacInterface.GetMethodTableForEEClass(ClrDataAddress eeClassReallyCanonM if (eeClassReallyCanonMT == 0 || value == null) throw new ArgumentException(); Contracts.IRuntimeTypeSystem contract = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle methodTableHandle = contract.GetTypeHandle(eeClassReallyCanonMT.ToTargetPointer(_target)); + ITypeHandle methodTableHandle = contract.GetTypeHandle(eeClassReallyCanonMT.ToTargetPointer(_target)); *value = methodTableHandle.Address.ToClrDataAddress(_target); } catch (global::System.Exception ex) @@ -2936,7 +2936,7 @@ int ISOSDacInterface.GetMethodTableName(ClrDataAddress mt, uint count, char* mtN throw new ArgumentException(); Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem; Contracts.ILoader loader = _target.Contracts.Loader; - Contracts.ITypeHandle methodTableHandle = typeSystemContract.GetTypeHandle(mt.ToTargetPointer(_target, overrideCheck: true)); + ITypeHandle methodTableHandle = typeSystemContract.GetTypeHandle(mt.ToTargetPointer(_target, overrideCheck: true)); if (typeSystemContract.IsFreeObjectMethodTable(methodTableHandle)) { OutputBufferHelpers.CopyStringToBuffer(mtName, count, pNeeded, "Free"); @@ -3251,7 +3251,7 @@ int ISOSDacInterface.GetObjectClassName(ClrDataAddress obj, uint count, char* cl Contracts.ILoader loader = _target.Contracts.Loader; TargetPointer mt = objectContract.GetMethodTableAddress(obj.ToTargetPointer(_target)); - Contracts.ITypeHandle typeHandle = rts.GetTypeHandle(mt); + ITypeHandle typeHandle = rts.GetTypeHandle(mt); TargetPointer modulePointer = rts.GetModule(typeHandle); if (modulePointer == TargetPointer.Null) @@ -5424,7 +5424,7 @@ int ISOSDacInterface6.GetMethodTableCollectibleData(ClrDataAddress mt, DacpMetho Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; ILoader loaderContract = _target.Contracts.Loader; - Contracts.ITypeHandle typeHandle = rtsContract.GetTypeHandle(mt.ToTargetPointer(_target)); + ITypeHandle typeHandle = rtsContract.GetTypeHandle(mt.ToTargetPointer(_target)); bool isCollectible = rtsContract.IsCollectible(typeHandle); if (isCollectible) @@ -5998,7 +5998,7 @@ int ISOSDacInterface8.GetAssemblyLoadContext(ClrDataAddress methodTable, ClrData Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; Contracts.ILoader loaderContract = _target.Contracts.Loader; - Contracts.ITypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); + ITypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); Contracts.ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(rtsContract.GetModule(methodTableHandle)); TargetPointer alc = loaderContract.GetAssemblyLoadContext(moduleHandle); *assemblyLoadContext = alc.ToClrDataAddress(_target); @@ -6726,7 +6726,7 @@ int ISOSDacInterface14.GetStaticBaseAddress(ClrDataAddress methodTable, ClrDataA throw new ArgumentException(); Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); + ITypeHandle typeHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); if (GCStaticsAddress != null) *GCStaticsAddress = rtsContract.GetGCStaticsBasePointer(typeHandle).ToClrDataAddress(_target); if (nonGCStaticsAddress != null) @@ -6767,7 +6767,7 @@ int ISOSDacInterface14.GetThreadStaticBaseAddress(ClrDataAddress methodTable, Cl Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; TargetPointer methodTablePtr = methodTable.ToTargetPointer(_target); TargetPointer threadPtr = thread.ToTargetPointer(_target); - Contracts.ITypeHandle typeHandle = rtsContract.GetTypeHandle(methodTablePtr); + ITypeHandle typeHandle = rtsContract.GetTypeHandle(methodTablePtr); ushort numThreadStaticFields = rtsContract.GetNumThreadStaticFields(typeHandle); if (numThreadStaticFields == 0) { @@ -6820,7 +6820,7 @@ int ISOSDacInterface14.GetMethodTableInitializationFlags(ClrDataAddress methodTa throw new NullReferenceException(); Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); + ITypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target)); *initializationStatus = (MethodTableInitializationFlags)0; if (rtsContract.IsClassInited(methodTableHandle)) *initializationStatus = MethodTableInitializationFlags.MethodTableInitialized; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs index 4c8138c6685497..6cf3a1d6bb0e58 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs @@ -359,7 +359,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, ITypeHan } stringBuilder.Append(name); - var instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); + ImmutableArray instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); if (instantiation.Length > 0) { stringBuilder.Append('<'); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs index be747c57896321..48434364f0f759 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs @@ -185,18 +185,18 @@ public static ITypeHandle GetExactOwningType(IRuntimeTypeSystem runtimeTypeSyste } while (true); } - public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.ITypeHandle typeHandle, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle, TypeNameFormat format) { AppendType(target, stringBuilder, typeHandle, ImmutableArray.Empty, format); } - public static void AppendType(Target target, StringBuilder stringBuilder, Contracts.ITypeHandle typeHandle, ImmutableArray typeInstantiation, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle, ImmutableArray typeInstantiation, TypeNameFormat format) { TypeNameBuilder builder = new(stringBuilder, target, format); AppendTypeCore(ref builder, typeHandle, typeInstantiation, format); } - private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandle typeHandle, ImmutableArray instantiation, TypeNameFormat format) + private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHandle, ImmutableArray instantiation, TypeNameFormat format) { bool toString = format.HasFlag(TypeNameFormat.FormatNamespace) && !format.HasFlag(TypeNameFormat.FormatFullInst) && !format.HasFlag(TypeNameFormat.FormatAssembly); @@ -213,13 +213,13 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, Contracts.ITypeHandl if (elemType != Contracts.CorElementType.ValueType) { typeSystemContract.IsArray(typeHandle, out uint rank); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); AppendParamTypeQualifier(ref tnb, elemType, rank); } else { tnb.TypeString.Append("VALUETYPE"); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, format & ~TypeNameFormat.FormatAssembly); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, format & ~TypeNameFormat.FormatAssembly); } } else if (typeSystemContract.IsGenericVariable(typeHandle, out TargetPointer modulePointer, out uint genericParamToken)) @@ -344,11 +344,11 @@ private static void AppendInst(ref TypeNameBuilder tnb, ImmutableArray.Empty, format | TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAssembly); + AppendTypeCore(ref tnb, arg, ImmutableArray.Empty, format | TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAssembly); } else { - AppendTypeCore(ref tnb, arg, ImmutableArray.Empty, format & (TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAngleBrackets)); + AppendTypeCore(ref tnb, arg, ImmutableArray.Empty, format & (TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAngleBrackets)); } tnb.CloseGenericArgument(); } diff --git a/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs b/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs index 48d181a851ca55..ec2c5ea08375a2 100644 --- a/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs @@ -83,7 +83,7 @@ public void HasRuntimeTypeSystemContract(MockTarget.Architecture arch) builder => freeObjectMethodTableAddress = builder.FreeObjectMethodTableAddress); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle handle = contract.GetTypeHandle(freeObjectMethodTableAddress); + ITypeHandle handle = contract.GetTypeHandle(freeObjectMethodTableAddress); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(contract.IsFreeObjectMethodTable(handle)); Assert.False(contract.IsObject(handle)); @@ -115,7 +115,7 @@ public void ValidateSystemObjectMethodTable(MockTarget.Architecture arch) rtsBuilder => systemObjectMethodTablePtr = rtsBuilder.SystemObjectMethodTable.Address); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle systemObjectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); + ITypeHandle systemObjectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); Assert.Equal(systemObjectMethodTablePtr.Value, systemObjectTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(systemObjectTypeHandle)); Assert.True(contract.IsObject(systemObjectTypeHandle)); @@ -155,7 +155,7 @@ public void ValidateSystemStringMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle systemStringTypeHandle = contract.GetTypeHandle(systemStringMethodTablePtr); + ITypeHandle systemStringTypeHandle = contract.GetTypeHandle(systemStringMethodTablePtr); Assert.Equal(systemStringMethodTablePtr.Value, systemStringTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(systemStringTypeHandle)); Assert.True(contract.IsString(systemStringTypeHandle)); @@ -265,7 +265,7 @@ public void ValidateGenericInstMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle genericInstanceTypeHandle = contract.GetTypeHandle(genericInstanceMethodTablePtr); + ITypeHandle genericInstanceTypeHandle = contract.GetTypeHandle(genericInstanceMethodTablePtr); Assert.Equal(genericInstanceMethodTablePtr.Value, genericInstanceTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(genericInstanceTypeHandle)); Assert.False(contract.IsString(genericInstanceTypeHandle)); @@ -321,7 +321,7 @@ public void ValidateArrayInstMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle arrayInstanceTypeHandle = contract.GetTypeHandle(arrayInstanceMethodTablePtr); + ITypeHandle arrayInstanceTypeHandle = contract.GetTypeHandle(arrayInstanceMethodTablePtr); Assert.Equal(arrayInstanceMethodTablePtr.Value, arrayInstanceTypeHandle.Address.Value); Assert.False(contract.IsFreeObjectMethodTable(arrayInstanceTypeHandle)); Assert.False(contract.IsString(arrayInstanceTypeHandle)); @@ -384,7 +384,7 @@ public void IsContinuationWithoutMetadata_ReturnsTrueForContinuationType(MockTar }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.True(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); Assert.False(contract.IsFreeObjectMethodTable(continuationTypeHandle)); Assert.False(contract.IsString(continuationTypeHandle)); @@ -483,11 +483,11 @@ public void ValidateMultidimArrayRank(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle rank4Handle = contract.GetTypeHandle(rank4MethodTablePtr); + ITypeHandle rank4Handle = contract.GetTypeHandle(rank4MethodTablePtr); Assert.True(contract.IsArray(rank4Handle, out uint rank4)); Assert.Equal(4u, rank4); - Contracts.ITypeHandle rank1Handle = contract.GetTypeHandle(rank1MultiDimMethodTablePtr); + ITypeHandle rank1Handle = contract.GetTypeHandle(rank1MultiDimMethodTablePtr); Assert.True(contract.IsArray(rank1Handle, out uint rank1)); Assert.Equal(1u, rank1); } @@ -517,10 +517,10 @@ public void IsContinuationWithoutMetadata_ReturnsFalseWhenGlobalIsNull(MockTarge }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); + ITypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(objectTypeHandle)); - Contracts.ITypeHandle childTypeHandle = contract.GetTypeHandle(childMethodTablePtr); + ITypeHandle childTypeHandle = contract.GetTypeHandle(childMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(childTypeHandle)); } @@ -554,7 +554,7 @@ public void ValidateContinuationMethodTablePointer(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.Equal(continuationInstanceMethodTablePtr.Value, continuationTypeHandle.Address.Value); Assert.True(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); } @@ -862,7 +862,7 @@ public void RequiresAlign8(MockTarget.Architecture arch, bool flagSet) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(methodTablePtr); + ITypeHandle typeHandle = contract.GetTypeHandle(methodTablePtr); Assert.Equal(flagSet, contract.RequiresAlign8(typeHandle)); } @@ -881,7 +881,7 @@ public void GetGCDescSeriesReturnsEmptyForNonMethodTable(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeDescHandle = contract.GetTypeHandle(typeDescAddress); + ITypeHandle typeDescHandle = contract.GetTypeHandle(typeDescAddress); Assert.Empty(contract.GetGCDescSeries(typeDescHandle)); } @@ -907,7 +907,7 @@ public void GetGCDescSeriesReturnsEmptyWhenNoGCPointers(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.False(contract.ContainsGCPointers(typeHandle)); Assert.Empty(contract.GetGCDescSeries(typeHandle)); } @@ -954,7 +954,7 @@ public void GetGCDescSeriesReturnsSingleSeries(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle).ToArray(); @@ -1009,7 +1009,7 @@ public void GetGCDescSeriesReturnsMultipleSeriesInOrder(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle).ToArray(); Assert.Equal(expectedSeries.Length, series.Length); @@ -1065,7 +1065,7 @@ public void GetGCDescSeriesReturnsSingleValueClassSeries(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); // Pass numComponents=1 because value-class GCDesc iterates one element per component. @@ -1124,7 +1124,7 @@ public void GetGCDescSeriesReturnsMultipleValueClassSeries(MockTarget.Architectu }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); // Pass numComponents=1 because value-class GCDesc iterates one element per component. (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle, 1).ToArray(); @@ -1185,7 +1185,7 @@ public void GetGCDescSeriesRegularSeriesWithArrayNumComponents(MockTarget.Archit }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); uint pointerSz = (uint)target.PointerSize; @@ -1243,7 +1243,7 @@ public void GetGCDescSeriesValueClassRepeatingWithArrayNumComponents(MockTarget. }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); uint elemSize = 2 * (uint)target.PointerSize; uint startOff = 3u * (uint)target.PointerSize; From 049c58cca8e5c0dc58f40cc1b4bdce8fe9681938 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 22:43:26 -0400 Subject: [PATCH 09/23] Preserve span APIs and flush cached type handles Keep the RuntimeTypeSystem collection API shape unchanged by using ReadOnlySpan over cached ITypeHandle arrays. This removes the unnecessary ImmutableArray API churn and builder allocations from the TypeHandle-to-ITypeHandle conversion. Clear ManagedTypeSource's cached ITypeHandle values on every flush because RuntimeTypeSystem invalidates its canonical handle instances. Continue to retain immutable CoreLib type layouts and field descriptors across forward execution. Add dump-test coverage for canonical handle resolution after a forward flush. Also correct the remaining ITypeHandle documentation and native TypeHandle terminology. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../design/datacontracts/ManagedTypeSource.md | 2 +- .../design/datacontracts/RuntimeTypeSystem.md | 20 +++++---- .../CdacAttributes.cs | 6 +-- .../Contracts/IRuntimeTypeSystem.cs | 6 +-- .../Contracts/ManagedTypeSource_1.cs | 16 ++++--- .../Contracts/RuntimeTypeSystem_1.cs | 45 +++++++++---------- .../StackWalk/GC/GcSignatureTypeProvider.cs | 2 +- .../ClrDataFrame.cs | 4 +- .../Dbi/DacDbiImpl.cs | 14 +++--- .../SigFormat.cs | 17 ++++--- .../TypeNameBuilder.cs | 33 +++++++------- .../DacDbi/DacDbiApproxTypeHandleDumpTests.cs | 4 +- .../DacDbi/DacDbiExactTypeHandleDumpTests.cs | 3 +- .../DumpTests/RuntimeTypeSystemDumpTests.cs | 17 +++++++ .../cdac/tests/UnitTests/TypeDescTests.cs | 2 +- 15 files changed, 104 insertions(+), 87 deletions(-) diff --git a/docs/design/datacontracts/ManagedTypeSource.md b/docs/design/datacontracts/ManagedTypeSource.md index cf612df51a3094..e0e62de5d70a87 100644 --- a/docs/design/datacontracts/ManagedTypeSource.md +++ b/docs/design/datacontracts/ManagedTypeSource.md @@ -21,7 +21,7 @@ bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info); // Throws InvalidOperationException if the type cannot be resolved. Target.TypeInfo GetTypeInfo(string fullyQualifiedName); -// Return true and populate `typeHandle` with the runtime ITypeHandle for the type, +// Return true and populate `typeHandle` with the cDAC ITypeHandle for the runtime type, // or false if the type cannot be resolved. bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle); ITypeHandle GetTypeHandle(string fullyQualifiedName); diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index 7302d735c13e17..641006848e0d52 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -35,7 +35,9 @@ internal enum CorElementType } ``` -A `ITypeHandle` is the runtime representation of the type information about a value. This can be constructed from the address of a `ITypeHandle` or a `MethodTable`. +An `ITypeHandle` is the cDAC representation of runtime type information. Consumers obtain +canonical handles from `RuntimeTypeSystem.GetTypeHandle` using the target address of a +runtime `TypeHandle` or `MethodTable`. ``` csharp partial interface IRuntimeTypeSystem : IContract @@ -116,7 +118,7 @@ partial interface IRuntimeTypeSystem : IContract public bool IsTrackedReferenceWithFinalizer(ITypeHandle typeHandle); public TargetPointer GetGCStaticsBasePointer(ITypeHandle typeHandle); public TargetPointer GetNonGCStaticsBasePointer(ITypeHandle typeHandle); - public virtual ImmutableArray GetInstantiation(ITypeHandle typeHandle); + public virtual ReadOnlySpan GetInstantiation(ITypeHandle typeHandle); public bool IsClassInited(ITypeHandle typeHandle); public bool IsInitError(ITypeHandle typeHandle); public virtual bool IsGenericTypeDefinition(ITypeHandle typeHandle); @@ -146,7 +148,7 @@ partial interface IRuntimeTypeSystem : IContract ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default); ITypeHandle GetPrimitiveType(CorElementType typeCode); bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token); - bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv); + bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv); bool IsPointer(ITypeHandle typeHandle); bool IsTypeDesc(ITypeHandle typeHandle); TargetPointer GetLoaderModule(ITypeHandle typeHandle); @@ -224,7 +226,7 @@ partial interface IRuntimeTypeSystem : IContract // Return true for an uninstantiated generic method public virtual bool IsGenericMethodDefinition(MethodDescHandle methodDesc); - public virtual ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDesc); + public virtual ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDesc); // Return mdTokenNil (0x06000000) if the method doesn't have a token, otherwise return the token of the method public virtual uint GetMethodToken(MethodDescHandle methodDesc); @@ -934,7 +936,7 @@ Contracts used: return threadContract.GetThreadLocalStaticBase(threadPtr, tlsIndexAddr); } - public ImmutableArray GetInstantiation(ITypeHandle TypeHandle) + public ReadOnlySpan GetInstantiation(ITypeHandle TypeHandle) { if (!typeHandle.IsMethodTable()) return default; @@ -1143,7 +1145,7 @@ Contracts used: private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle potentialMatch, ImmutableArray typeArguments) { - ImmutableArray instantiation = GetInstantiation(potentialMatch); + ReadOnlySpan instantiation = GetInstantiation(potentialMatch); if (instantiation.Length != typeArguments.Length) return false; @@ -1173,7 +1175,7 @@ Contracts used: private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) { - if (!IsFunctionPointer(candidate, out ImmutableArray candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) + if (!IsFunctionPointer(candidate, out ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) return false; if (candidateCallConv != callConv) return false; @@ -1266,7 +1268,7 @@ Contracts used: return false; } - public bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv) + public bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) { retAndArgTypes = default; callConv = default; @@ -1598,7 +1600,7 @@ And the various apis are implemented with the following algorithms return ((int)Flags2 & (int)InstantiatedMethodDescFlags2.KindMask) == (int)InstantiatedMethodDescFlags2.GenericMethodDefinition; } - public ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) + public ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) { MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs index 56fc9bb58a1fe0..cbbd3b9184f20e 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs @@ -31,9 +31,9 @@ public CdacTypeAttribute(params string[] names) public string[] Names { get; } /// - /// When true, the generator emits a ITypeHandle(Target) - /// accessor that resolves the runtime ITypeHandle by trying each - /// candidate name against IManagedTypeSource. + /// When true, the generator emits a TypeHandle(Target) + /// accessor returning an ITypeHandle by trying each candidate name + /// against IManagedTypeSource. /// public bool HasTypeHandle { get; set; } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index 868a795932d8ef..68d668a9aab295 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -231,7 +231,7 @@ public interface IRuntimeTypeSystem : IContract TargetPointer GetNonGCThreadStaticsBasePointer(ITypeHandle typeHandle, TargetPointer threadPtr) => throw new NotImplementedException(); - ImmutableArray GetInstantiation(ITypeHandle typeHandle) => throw new NotImplementedException(); + ReadOnlySpan GetInstantiation(ITypeHandle typeHandle) => throw new NotImplementedException(); public bool IsClassInited(ITypeHandle typeHandle) => throw new NotImplementedException(); public bool IsInitError(ITypeHandle typeHandle) => throw new NotImplementedException(); bool IsGenericTypeDefinition(ITypeHandle typeHandle) => throw new NotImplementedException(); @@ -263,7 +263,7 @@ public interface IRuntimeTypeSystem : IContract ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default) => throw new NotImplementedException(); ITypeHandle GetPrimitiveType(CorElementType typeCode) => throw new NotImplementedException(); bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token) => throw new NotImplementedException(); - bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv) => throw new NotImplementedException(); + bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) => throw new NotImplementedException(); bool IsPointer(ITypeHandle typeHandle) => throw new NotImplementedException(); bool IsTypeDesc(ITypeHandle typeHandle) => throw new NotImplementedException(); TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) => throw new NotImplementedException(); @@ -276,7 +276,7 @@ public interface IRuntimeTypeSystem : IContract // Return true for an uninstantiated generic method bool IsGenericMethodDefinition(MethodDescHandle methodDesc) => throw new NotImplementedException(); - ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDesc) => throw new NotImplementedException(); + ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDesc) => throw new NotImplementedException(); GenericContextLoc GetGenericContextLoc(MethodDescHandle methodDescHandle) => throw new NotImplementedException(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs index 6a4ccba7b41763..cc8e62da75bda1 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs @@ -25,15 +25,19 @@ public ManagedTypeSource_1(Target target) public void Flush(FlushScope scope) { - // They are safe to retain across FlushScope.ForwardExecution because - // ManagedTypeSource_1 only resolves names in System.Private.CoreLib, which - // is loaded into the non-collectible default AssemblyLoadContext at runtime - // startup and whose ECMA metadata never changes for the process lifetime. + // RuntimeTypeSystem invalidates its canonical ITypeHandle instances on every + // flush, so this cache must be cleared even when the underlying CoreLib types + // remain loaded and immutable. + _typeHandleCache.Clear(); + + // Type layouts and field descriptors are safe to retain across + // FlushScope.ForwardExecution because ManagedTypeSource_1 only resolves names + // in System.Private.CoreLib, which is loaded into the non-collectible default + // AssemblyLoadContext at runtime startup and whose ECMA metadata never changes. if (scope != FlushScope.All) return; _typeInfoCache.Clear(); - _typeHandleCache.Clear(); _fieldDescCache.Clear(); } @@ -268,7 +272,7 @@ private bool TryResolveType(string managedFqName, out ITypeHandle th, [NotNullWh if (!TryFindTypeDefinition(moduleHandle, managedFqName, out mdReader, out TypeDefinitionHandle typeDefHandle)) return false; - // Look up the runtime ITypeHandle via the module's TypeDef → MethodTable map. + // Look up the cDAC ITypeHandle via the module's TypeDef → MethodTable map. int token = MetadataTokens.GetToken((EntityHandle)typeDefHandle); TargetPointer typeDefToMethodTable = loader.GetLookupTables(moduleHandle).TypeDefToMethodTable; TargetPointer typeHandlePtr = loader.GetModuleLookupMapElement(typeDefToMethodTable, (uint)token, out _); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index e5c9ac23dc6fa8..36fd09629a2113 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -369,16 +369,15 @@ private InstantiatedMethodDesc(Target target, TargetPointer methodDescPointer) TargetPointer perInstInfo = _desc.PerInstInfo; if ((perInstInfo == TargetPointer.Null) || (numGenericArgs == 0)) { - Instantiation = ImmutableArray.Empty; + Instantiation = System.Array.Empty(); } else { - var builder = ImmutableArray.CreateBuilder(numGenericArgs); + Instantiation = new ITypeHandle[numGenericArgs]; for (int i = 0; i < numGenericArgs; i++) { - builder.Add(rts.GetTypeHandle(target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)i))); + Instantiation[i] = rts.GetTypeHandle(target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)i)); } - Instantiation = builder.MoveToImmutable(); } } @@ -387,7 +386,7 @@ private InstantiatedMethodDesc(Target target, TargetPointer methodDescPointer) internal bool IsGenericMethodDefinition => HasFlags(InstantiatedMethodDescFlags2.KindMask, InstantiatedMethodDescFlags2.GenericMethodDefinition); internal bool HasPerInstInfo => _desc.PerInstInfo != TargetPointer.Null; internal bool HasMethodInstantiation => IsGenericMethodDefinition || HasPerInstInfo; - public ImmutableArray Instantiation { get; } + public ITypeHandle[] Instantiation { get; } } private sealed class DynamicMethodDesc : IData @@ -790,7 +789,7 @@ private int GetVectorHFAElementSize(ITypeHandle typeHandle) if (elemSize == 0) return 0; - ImmutableArray instantiation = ((IRuntimeTypeSystem)this).GetInstantiation(typeHandle); + ReadOnlySpan instantiation = ((IRuntimeTypeSystem)this).GetInstantiation(typeHandle); if (instantiation.Length < 1) return 0; @@ -1003,14 +1002,14 @@ public TargetPointer GetNonGCStaticsBasePointer(ITypeHandle typeHandle) return dynamicStaticsInfo.NonGCStatics; } - public ImmutableArray GetInstantiation(ITypeHandle typeHandle) + public ReadOnlySpan GetInstantiation(ITypeHandle typeHandle) { if (!typeHandle.IsMethodTable()) - return ImmutableArray.Empty; + return default; MethodTable methodTable = _methodTables[typeHandle.Address]; if (!methodTable.Flags.HasInstantiation) - return ImmutableArray.Empty; + return default; return _target.ProcessedData.GetOrAdd(typeHandle.Address).TypeHandles; } @@ -1037,7 +1036,7 @@ private sealed class TypeInstantiation : IData { public static TypeInstantiation Create(Target target, TargetPointer address) => new TypeInstantiation(target, address); - public ImmutableArray TypeHandles { get; } + public ITypeHandle[] TypeHandles { get; } private TypeInstantiation(Target target, TargetPointer typePointer) { RuntimeTypeSystem_1 rts = (RuntimeTypeSystem_1)target.Contracts.RuntimeTypeSystem; @@ -1053,12 +1052,11 @@ private TypeInstantiation(Target target, TargetPointer typePointer) TargetPointer dictionaryPointer = target.ReadPointer(perInstInfo + (ulong)target.PointerSize * (ulong)(genericsDictInfo.NumDicts - 1)); int numberOfGenericArgs = genericsDictInfo.NumTypeArgs; - var builder = ImmutableArray.CreateBuilder(numberOfGenericArgs); + TypeHandles = new ITypeHandle[numberOfGenericArgs]; for (int i = 0; i < numberOfGenericArgs; i++) { - builder.Add(rts.GetTypeHandle(target.ReadPointer(dictionaryPointer + (ulong)target.PointerSize * (ulong)i))); + TypeHandles[i] = rts.GetTypeHandle(target.ReadPointer(dictionaryPointer + (ulong)target.PointerSize * (ulong)i)); } - TypeHandles = builder.MoveToImmutable(); } } @@ -1078,7 +1076,7 @@ public bool ContainsGenericVariables(ITypeHandle typeHandle) else if (type == CorElementType.FnPtr) { - _ = IsFunctionPointer(typeHandle, out ImmutableArray signatureTypeArgs, out _); + _ = IsFunctionPointer(typeHandle, out ReadOnlySpan signatureTypeArgs, out _); foreach (ITypeHandle sigTypeArg in signatureTypeArgs) { if (ContainsGenericVariables(sigTypeArg)) @@ -1259,7 +1257,7 @@ private ITypeHandle GetRootTypeParam(ITypeHandle typeHandle) private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle potentialMatch, ImmutableArray typeArguments) { - ImmutableArray instantiation = GetInstantiation(potentialMatch); + ReadOnlySpan instantiation = GetInstantiation(potentialMatch); if (instantiation.Length != typeArguments.Length) return false; @@ -1289,7 +1287,7 @@ private bool ArrayPtrMatch(ITypeHandle elementType, CorElementType corElementTyp private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) { - if (!IsFunctionPointer(candidate, out ImmutableArray candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) + if (!IsFunctionPointer(candidate, out ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) return false; if (candidateCallConv != callConv) return false; @@ -1464,9 +1462,9 @@ public bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, return false; } - public bool IsFunctionPointer(ITypeHandle typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv) + public bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) { - retAndArgTypes = ImmutableArray.Empty; + retAndArgTypes = default; callConv = default; if (!typeHandle.IsTypeDesc()) @@ -1531,7 +1529,7 @@ private sealed class FunctionPointerRetAndArgs : IData new FunctionPointerRetAndArgs(target, address); - public ImmutableArray TypeHandles { get; } + public ITypeHandle[] TypeHandles { get; } private FunctionPointerRetAndArgs(Target target, TargetPointer typePointer) { RuntimeTypeSystem_1 rts = (RuntimeTypeSystem_1)target.Contracts.RuntimeTypeSystem; @@ -1540,12 +1538,11 @@ private FunctionPointerRetAndArgs(Target target, TargetPointer typePointer) TargetPointer retAndArgs = fnPtrTypeDesc.RetAndArgTypes; int numberOfRetAndArgTypes = checked((int)fnPtrTypeDesc.NumArgs + 1); - var builder = ImmutableArray.CreateBuilder(numberOfRetAndArgTypes); + TypeHandles = new ITypeHandle[numberOfRetAndArgTypes]; for (int i = 0; i < numberOfRetAndArgTypes; i++) { - builder.Add(rts.GetTypeHandle(target.ReadPointer(retAndArgs + (ulong)target.PointerSize * (ulong)i))); + TypeHandles[i] = rts.GetTypeHandle(target.ReadPointer(retAndArgs + (ulong)target.PointerSize * (ulong)i)); } - TypeHandles = builder.MoveToImmutable(); } } @@ -1613,12 +1610,12 @@ public bool IsGenericMethodDefinition(MethodDescHandle methodDescHandle) return AsInstantiatedMethodDesc(methodDesc).IsGenericMethodDefinition; } - public ImmutableArray GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) + public ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) { MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; if (methodDesc.Classification != MethodClassification.Instantiated) - return ImmutableArray.Empty; + return default; return AsInstantiatedMethodDesc(methodDesc).Instantiation; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs index a3b28755cfef91..a5cd3db0d6d509 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs @@ -117,7 +117,7 @@ public GcTypeKind GetGenericTypeParameter(GcSignatureContext genericContext, int return ClassifyTypeHandle(rts.GetTypeParam(classCtx)); } - ImmutableArray instantiation = rts.GetInstantiation(classCtx); + ReadOnlySpan instantiation = rts.GetInstantiation(classCtx); if ((uint)index >= (uint)instantiation.Length) return GcTypeKind.Ref; return ClassifyTypeHandle(instantiation[index]); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs index f14cb0d2360f3d..d4d5db77e48e52 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs @@ -742,7 +742,7 @@ public FlagSignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHan try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - ImmutableArray methodInst = rts.GetGenericMethodInstantiation(mdh); + ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(mdh); return ResolveGenericParam(rts, methodInst[index]); } catch (System.Exception) { return ((uint)ClrDataValueFlag.DEFAULT, -1); } @@ -755,7 +755,7 @@ public FlagSignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHan IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = rts.GetMethodTable(mdh); ITypeHandle declaringType = rts.GetTypeHandle(mtAddr); - ImmutableArray typeInst = rts.GetInstantiation(declaringType); + ReadOnlySpan typeInst = rts.GetInstantiation(declaringType); return ResolveGenericParam(rts, typeInst[index]); } catch (System.Exception) { return ((uint)ClrDataValueFlag.DEFAULT, -1); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs index e04206b76d90dd..d74c3a49cf459c 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs @@ -3127,10 +3127,10 @@ public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, ui TargetPointer specMethodMtPtr = rts.GetMethodTable(pSpecificMethod); ITypeHandle thSpecMethodMt = rts.GetTypeHandle(specMethodMtPtr); ITypeHandle thMatchingParent = GetMethodTableMatchingParentClass(rts, thSpecificClass, thSpecMethodMt); - ImmutableArray classInst = thMatchingParent.IsNull - ? ImmutableArray.Empty + ReadOnlySpan classInst = thMatchingParent.IsNull + ? default : rts.GetInstantiation(thMatchingParent); - ImmutableArray methodInst = rts.GetGenericMethodInstantiation(pSpecificMethod); + ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(pSpecificMethod); cClassParams = (uint)classInst.Length; *pcGenericClassTypeParams = cClassParams; @@ -3398,7 +3398,7 @@ public int EnumerateTypeHandleParams(ulong vmTypeHandle, IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; ITypeHandle typeHandle = rts.GetTypeHandle(new TargetPointer(vmTypeHandle)); - ImmutableArray instantiation = rts.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); DebuggerIPCE_ExpandedTypeData entry; for (int i = 0; i < instantiation.Length; i++) @@ -5862,7 +5862,7 @@ private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle return rts.GetSignatureCorElementType(typeHandle); } - // Mirrors native ITypeHandle::UpCastTypeIfNeeded — for continuation types, returns the + // Mirrors native TypeHandle::UpCastTypeIfNeeded — for continuation types, returns the // parent (continuation base) type handle instead. private static ITypeHandle UpCastTypeIfNeeded(IRuntimeTypeSystem rts, ITypeHandle typeHandle) { @@ -5909,7 +5909,7 @@ private void FillClassTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, D Contracts.ILoader loader = _target.Contracts.Loader; Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); - ImmutableArray instantiation = rts.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length > 0) { // Generic instantiation — set the type handle so the debugger can fetch type arguments @@ -5965,7 +5965,7 @@ internal void FillBasicTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, Contracts.ILoader loader = _target.Contracts.Loader; Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr); - ImmutableArray instantiation = rts.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length > 0) { WriteLittleEndian(ref typeInfo.vmTypeHandle, typeHandle.Address.Value); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs index 6cf3a1d6bb0e58..a846d3defc1072 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Immutable; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; @@ -19,8 +18,8 @@ public static unsafe void AppendSigFormat(Target target, string? memberName, string? className, string? namespaceName, - ImmutableArray typeInstantiation, - ImmutableArray methodInstantiation, + ReadOnlySpan typeInstantiation, + ReadOnlySpan methodInstantiation, bool CStringParmsOnly) { fixed (byte* pSignature = signature) @@ -37,8 +36,8 @@ public static void AppendSigFormat(Target target, string? memberName, string? className, string? namespaceName, - ImmutableArray typeInstantiation, - ImmutableArray methodInstantiation, + ReadOnlySpan typeInstantiation, + ReadOnlySpan methodInstantiation, bool CStringParmsOnly) { SignatureHeader header = signature.ReadSignatureHeader(); @@ -96,8 +95,8 @@ public static void AppendSigFormat(Target target, private static unsafe void AddTypeString(Target target, StringBuilder stringBuilder, ref BlobReader signature, - ImmutableArray typeInstantiation, - ImmutableArray methodInstantiation, + ReadOnlySpan typeInstantiation, + ReadOnlySpan methodInstantiation, MetadataReader? metadata) { string _namespace; @@ -359,7 +358,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, ITypeHan } stringBuilder.Append(name); - ImmutableArray instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = runtimeTypeSystem.GetInstantiation(typeHandle); if (instantiation.Length > 0) { stringBuilder.Append('<'); @@ -415,7 +414,7 @@ private static void AddType(Target target, StringBuilder stringBuilder, ITypeHan return; case CorElementType.FnPtr: - runtimeTypeSystem.IsFunctionPointer(typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv); + runtimeTypeSystem.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv); SignatureHeader header = new SignatureHeader((byte)callConv); AddType(target, stringBuilder, retAndArgTypes[0]); stringBuilder.Append(" ("); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs index 48434364f0f759..89b42c4375f3a1 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; @@ -60,10 +59,10 @@ private TypeNameBuilder(StringBuilder typeString, Target target, TypeNameFormat public static void AppendMethodInternal(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, TypeNameFormat format) { - AppendMethodImpl(target, stringBuilder, method, ImmutableArray.Empty, format); + AppendMethodImpl(target, stringBuilder, method, default, format); } - public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, ImmutableArray typeInstantiation, TypeNameFormat format) + public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, Contracts.MethodDescHandle method, ReadOnlySpan typeInstantiation, TypeNameFormat format) { IRuntimeTypeSystem runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; ILoader loader = target.Contracts.Loader; @@ -130,7 +129,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, } } - var genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); + ReadOnlySpan genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); if (genericMethodInstantiation.Length > 0 && !runtimeTypeSystem.IsGenericMethodDefinition(method)) { AppendInst(target, stringBuilder, genericMethodInstantiation, format); @@ -143,7 +142,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, runtimeTypeSystem.GetModule(runtimeTypeSystem.GetTypeHandle(runtimeTypeSystem.GetMethodTable(method)))); MetadataReader? reader = target.Contracts.EcmaMetadata.GetMetadata(methodModule); - var typeInstantiationSigFormat = ImmutableArray.Empty; + ReadOnlySpan typeInstantiationSigFormat = default; if (!th.IsNull) { typeInstantiationSigFormat = runtimeTypeSystem.GetInstantiation(th); @@ -151,7 +150,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, { // For arrays, fill in the instantiation with the element type handle // See MethodTable::GetArrayInstantiation for coreclr equivalent - typeInstantiationSigFormat = ImmutableArray.Create(runtimeTypeSystem.GetTypeParam(th)); + typeInstantiationSigFormat = new[] { runtimeTypeSystem.GetTypeParam(th) }; } } @@ -187,16 +186,16 @@ public static ITypeHandle GetExactOwningType(IRuntimeTypeSystem runtimeTypeSyste public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle, TypeNameFormat format) { - AppendType(target, stringBuilder, typeHandle, ImmutableArray.Empty, format); + AppendType(target, stringBuilder, typeHandle, default, format); } - public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle, ImmutableArray typeInstantiation, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle, ReadOnlySpan typeInstantiation, TypeNameFormat format) { TypeNameBuilder builder = new(stringBuilder, target, format); AppendTypeCore(ref builder, typeHandle, typeInstantiation, format); } - private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHandle, ImmutableArray instantiation, TypeNameFormat format) + private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHandle, ReadOnlySpan instantiation, TypeNameFormat format) { bool toString = format.HasFlag(TypeNameFormat.FormatNamespace) && !format.HasFlag(TypeNameFormat.FormatFullInst) && !format.HasFlag(TypeNameFormat.FormatAssembly); @@ -213,13 +212,13 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHand if (elemType != Contracts.CorElementType.ValueType) { typeSystemContract.IsArray(typeHandle, out uint rank); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), default, (TypeNameFormat)(format & ~TypeNameFormat.FormatAssembly)); AppendParamTypeQualifier(ref tnb, elemType, rank); } else { tnb.TypeString.Append("VALUETYPE"); - AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), ImmutableArray.Empty, format & ~TypeNameFormat.FormatAssembly); + AppendTypeCore(ref tnb, typeSystemContract.GetTypeParam(typeHandle), default, format & ~TypeNameFormat.FormatAssembly); } } else if (typeSystemContract.IsGenericVariable(typeHandle, out TargetPointer modulePointer, out uint genericParamToken)) @@ -242,7 +241,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHand tnb.AddName(reader.GetString(genericParam.Name)); format &= ~TypeNameFormat.FormatAssembly; } - else if (typeSystemContract.IsFunctionPointer(typeHandle, out ImmutableArray retAndArgTypes, out SignatureCallingConvention callConv)) + else if (typeSystemContract.IsFunctionPointer(typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv)) { if (format.HasFlag(TypeNameFormat.FormatNamespace)) { @@ -300,7 +299,7 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHand if (format.HasFlag(TypeNameFormat.FormatNamespace) || format.HasFlag(TypeNameFormat.FormatAssembly)) { - ImmutableArray instantiationSpan = typeSystemContract.GetInstantiation(typeHandle); + ReadOnlySpan instantiationSpan = typeSystemContract.GetInstantiation(typeHandle); if ((instantiationSpan.Length > 0) && (!typeSystemContract.IsGenericTypeDefinition(typeHandle) || toString)) { @@ -330,13 +329,13 @@ private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHand // Append a square-bracket-enclosed, comma-separated list of n type parameters in inst to the string s // and enclose each parameter in square brackets to disambiguate the commas // The following flags in the FormatFlags argument are significant: FormatNamespace FormatFullInst FormatAssembly FormatNoVersion - private static void AppendInst(Target target, StringBuilder stringBuilder, ImmutableArray inst, TypeNameFormat format) + private static void AppendInst(Target target, StringBuilder stringBuilder, ReadOnlySpan inst, TypeNameFormat format) { TypeNameBuilder tnb = new(stringBuilder, target, format, initialStateIsName: true); AppendInst(ref tnb, inst, format); } - private static void AppendInst(ref TypeNameBuilder tnb, ImmutableArray inst, TypeNameFormat format) + private static void AppendInst(ref TypeNameBuilder tnb, ReadOnlySpan inst, TypeNameFormat format) { tnb.OpenGenericArguments(); foreach (ITypeHandle arg in inst) @@ -344,11 +343,11 @@ private static void AppendInst(ref TypeNameBuilder tnb, ImmutableArray.Empty, format | TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAssembly); + AppendTypeCore(ref tnb, arg, default, format | TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAssembly); } else { - AppendTypeCore(ref tnb, arg, ImmutableArray.Empty, format & (TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAngleBrackets)); + AppendTypeCore(ref tnb, arg, default, format & (TypeNameFormat.FormatNamespace | TypeNameFormat.FormatAngleBrackets)); } tnb.CloseGenericArgument(); } diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs index cbdcc93e613b6a..1d76fd8f62a561 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs @@ -170,7 +170,7 @@ private static unsafe void FillTypeNodes(DacDbiImpl dbi, IRuntimeTypeSystem rts, case CorElementType.Class: case CorElementType.ValueType: { - ImmutableArray inst = rts.GetInstantiation(th); + ReadOnlySpan inst = rts.GetInstantiation(th); uint numTypeArgs = (uint)inst.Length; pSelf->numTypeArgs = BitConverter.IsLittleEndian ? numTypeArgs : System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(numTypeArgs); for (int i = 0; i < inst.Length; i++) @@ -268,7 +268,7 @@ private ITypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, th = rts.GetTypeHandle(parentMT); } - ImmutableArray inst = rts.GetInstantiation(th); + ReadOnlySpan inst = rts.GetInstantiation(th); if (inst.Length == 0) return th; diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs index 1b0418ee891e54..83f0996a2d50ef 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Immutable; using Microsoft.Diagnostics.DataContractReader.Contracts; using Microsoft.Diagnostics.DataContractReader.Legacy; using Microsoft.Diagnostics.DataContractReader.TestInfrastructure; @@ -109,7 +108,7 @@ private static DebuggerIPCE_BasicTypeData[] BuildArgInfoList(DacDbiImpl dbi, IRu return one; } - ImmutableArray instantiation = rts.GetInstantiation(typeHandle); + ReadOnlySpan instantiation = rts.GetInstantiation(typeHandle); if (instantiation.Length == 0) return Array.Empty(); diff --git a/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs index f01c9da1a06d08..5ebce7f22bc981 100644 --- a/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs @@ -255,6 +255,23 @@ public void RuntimeTypeSystem_IsCorElementTypeObjRef_AreConsistent(TestConfigura Assert.False(rts.IsCorElementTypeObjRef(rts.GetInternalCorElementType(intPtrHandle))); } + [ConditionalTheory] + [MemberData(nameof(TestConfigurations))] + public void ManagedTypeSource_TypeHandleIsCanonicalAfterForwardFlush(TestConfiguration config) + { + InitializeDumpTest(config); + + ITypeHandle first = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.IntPtr"); + + Target.Flush(FlushScope.ForwardExecution); + + ITypeHandle second = Target.Contracts.ManagedTypeSource.GetTypeHandle("System.IntPtr"); + ITypeHandle direct = Target.Contracts.RuntimeTypeSystem.GetTypeHandle(second.Address); + + Assert.NotSame(first, second); + Assert.Same(second, direct); + } + [ConditionalTheory] [MemberData(nameof(TestConfigurations))] public void RuntimeTypeSystem_ObjectMethodTableHasIntroducedMethods(TestConfiguration config) diff --git a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs index 8c606c991b0804..f4c54caa052607 100644 --- a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs @@ -162,7 +162,7 @@ public void IsFunctionPointer(MockTarget.Architecture arch) // Function pointer IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem; ITypeHandle handle = rts.GetTypeHandle(GetTypeDescHandlePointer(funcPtr)); - bool res = rts.IsFunctionPointer(handle, out ImmutableArray actualRetAndArgTypes, out SignatureCallingConvention actualCallConv); + bool res = rts.IsFunctionPointer(handle, out ReadOnlySpan actualRetAndArgTypes, out SignatureCallingConvention actualCallConv); Assert.True(res); Assert.Equal(callConv, (byte)actualCallConv); Assert.Equal(retAndArgTypesHandle.Length, actualRetAndArgTypes.Length); From e83472fb271604b0636bd4c439a0fbfad6290594 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 14 Jul 2026 22:48:24 -0400 Subject: [PATCH 10/23] Address latest ITypeHandle review feedback - Default ArgumentLocation handle properties to ITypeHandle.Null so omitted object-initializer members preserve the old zero-handle semantics. - Compare TargetTypeHandle addresses with TargetPointer.Null. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../Contracts/CallingConvention/ArgumentLocation.cs | 8 ++++++-- .../RuntimeTypeSystem/TypeHandleImplementations.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs index 25f3f962cdfe83..a523a023ea37d6 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs @@ -7,9 +7,13 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal readonly struct ArgumentLocation { + public ArgumentLocation() + { + } + public int Offset { get; init; } public CorElementType ElementType { get; init; } - public ITypeHandle TypeHandle { get; init; } + public ITypeHandle TypeHandle { get; init; } = ITypeHandle.Null; public bool IsThis { get; init; } public bool IsValueTypeThis { get; init; } public bool IsParamType { get; init; } @@ -30,7 +34,7 @@ internal readonly struct ArgumentLocation // For generic-instantiation parameters with an uncached closed ITypeHandle, // the open generic MethodTable (e.g. Span for a Span arg) so // encoders can inspect type structure as a fallback. - public ITypeHandle OpenGenericType { get; init; } + public ITypeHandle OpenGenericType { get; init; } = ITypeHandle.Null; // SystemV-AMD64 struct passed in registers. Offset is the StructInRegsOffset // sentinel; the encoder consumes SysVEightByteDescriptor + SysVIdxGenReg. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs index 9022da7ecc8f14..e959bdc5cc693f 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs @@ -15,5 +15,5 @@ internal TargetTypeHandle(TargetPointer address) } public TargetPointer Address { get; } - public bool IsNull => Address == 0; + public bool IsNull => Address == TargetPointer.Null; } From bd8e42015369f8f6b7c8c304b843c49fc45c6b50 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Wed, 15 Jul 2026 02:31:52 -0400 Subject: [PATCH 11/23] Use TargetPointer.Null in type handle helpers Use the explicit TargetPointer null sentinel for type-handle address checks and the TypeDescAddress failure result. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../RuntimeTypeSystemHelpers/ExtensionMethods.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs index 2ceafa34213cd6..133741a8a8fb5a 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs @@ -9,18 +9,18 @@ internal static class ExtensionMethods { public static bool IsTypeDesc(this ITypeHandle type) { - return type.Address != 0 && ((ulong)type.Address & (ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask) == (ulong)RuntimeTypeSystem_1.TypeHandleBits.TypeDesc; + return type.Address != TargetPointer.Null && ((ulong)type.Address & (ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask) == (ulong)RuntimeTypeSystem_1.TypeHandleBits.TypeDesc; } public static bool IsMethodTable(this ITypeHandle type) { - return type.Address != 0 && ((ulong)type.Address & (ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask) == (ulong)RuntimeTypeSystem_1.TypeHandleBits.MethodTable; + return type.Address != TargetPointer.Null && ((ulong)type.Address & (ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask) == (ulong)RuntimeTypeSystem_1.TypeHandleBits.MethodTable; } public static TargetPointer TypeDescAddress(this ITypeHandle type) { if (!type.IsTypeDesc()) - return 0; + return TargetPointer.Null; return (ulong)type.Address & ~(ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask; } From 849cc3359c0b17773d7a7f6a04ea3b9e95087530 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Wed, 15 Jul 2026 04:41:33 -0400 Subject: [PATCH 12/23] Remove unused ImmutableArray import Remove the stale System.Collections.Immutable using left after restoring ReadOnlySpan in TypeDescTests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs index f4c54caa052607..537f77e93fc480 100644 --- a/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Immutable; using System.Linq; using System.Reflection.Metadata; using Microsoft.Diagnostics.DataContractReader.Contracts; From b620b5ebd99112cccb3a376ceee5f662d78f8697 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Wed, 15 Jul 2026 09:47:08 -0400 Subject: [PATCH 13/23] Preserve default ArgumentLocation handle semantics without a constructor Use nullable backing fields with null-coalescing getters for TypeHandle and OpenGenericType. This preserves the old zero-valued TypeHandle behavior for new and default(ArgumentLocation), including zero-initialized arrays, without requiring an explicit parameterless struct constructor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../CallingConvention/ArgumentLocation.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs index a523a023ea37d6..cdd5195973c336 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs @@ -7,13 +7,16 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal readonly struct ArgumentLocation { - public ArgumentLocation() - { - } + private readonly ITypeHandle? _typeHandle; + private readonly ITypeHandle? _openGenericType; public int Offset { get; init; } public CorElementType ElementType { get; init; } - public ITypeHandle TypeHandle { get; init; } = ITypeHandle.Null; + public ITypeHandle TypeHandle + { + get => _typeHandle ?? ITypeHandle.Null; + init => _typeHandle = value; + } public bool IsThis { get; init; } public bool IsValueTypeThis { get; init; } public bool IsParamType { get; init; } @@ -34,7 +37,11 @@ public ArgumentLocation() // For generic-instantiation parameters with an uncached closed ITypeHandle, // the open generic MethodTable (e.g. Span for a Span arg) so // encoders can inspect type structure as a fallback. - public ITypeHandle OpenGenericType { get; init; } = ITypeHandle.Null; + public ITypeHandle OpenGenericType + { + get => _openGenericType ?? ITypeHandle.Null; + init => _openGenericType = value; + } // SystemV-AMD64 struct passed in registers. Offset is the StructInRegsOffset // sentinel; the encoder consumes SysVEightByteDescriptor + SysVIdxGenReg. From fcb4ce83a055d3b853eb87adf93a1098dd3d5340 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Thu, 16 Jul 2026 13:11:21 -0400 Subject: [PATCH 14/23] Simplify ArgumentLocation and use explicit types Keep ArgumentLocation as a plain readonly struct; its control-flow-specific consumers do not read omitted handle properties. Replace the remaining PR-added var declarations with explicit ITypeHandle/span types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../CallingConvention/ArgumentLocation.cs | 15 ++------------- .../Contracts/ManagedTypeSource_1.cs | 2 +- .../StackWalk/GC/GcSignatureTypeProvider.cs | 2 +- .../cdac/tests/UnitTests/MethodDescTests.cs | 4 ++-- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs index cdd5195973c336..25f3f962cdfe83 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs @@ -7,16 +7,9 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal readonly struct ArgumentLocation { - private readonly ITypeHandle? _typeHandle; - private readonly ITypeHandle? _openGenericType; - public int Offset { get; init; } public CorElementType ElementType { get; init; } - public ITypeHandle TypeHandle - { - get => _typeHandle ?? ITypeHandle.Null; - init => _typeHandle = value; - } + public ITypeHandle TypeHandle { get; init; } public bool IsThis { get; init; } public bool IsValueTypeThis { get; init; } public bool IsParamType { get; init; } @@ -37,11 +30,7 @@ public ITypeHandle TypeHandle // For generic-instantiation parameters with an uncached closed ITypeHandle, // the open generic MethodTable (e.g. Span for a Span arg) so // encoders can inspect type structure as a fallback. - public ITypeHandle OpenGenericType - { - get => _openGenericType ?? ITypeHandle.Null; - init => _openGenericType = value; - } + public ITypeHandle OpenGenericType { get; init; } // SystemV-AMD64 struct passed in registers. Offset is the StructInRegsOffset // sentinel; the encoder consumes SysVEightByteDescriptor + SysVIdxGenReg. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs index cc8e62da75bda1..212138e8d07c2e 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs @@ -95,7 +95,7 @@ public ITypeHandle GetTypeHandle(string fullyQualifiedName) public bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle) { - if (_typeHandleCache.TryGetValue(fullyQualifiedName, out var cached)) + if (_typeHandleCache.TryGetValue(fullyQualifiedName, out ITypeHandle? cached)) { typeHandle = cached; return !typeHandle.IsNull; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs index a5cd3db0d6d509..3c380e16f1ac6d 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs @@ -87,7 +87,7 @@ public GcTypeKind GetGenericMethodParameter(GcSignatureContext genericContext, i { try { - var instantiation = _target.Contracts.RuntimeTypeSystem.GetGenericMethodInstantiation(genericContext.MethodContext); + ReadOnlySpan instantiation = _target.Contracts.RuntimeTypeSystem.GetGenericMethodInstantiation(genericContext.MethodContext); if ((uint)index >= (uint)instantiation.Length) return GcTypeKind.Ref; return ClassifyTypeHandle(instantiation[index]); diff --git a/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs b/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs index ba74f08a00da8f..a8a61d0a8d1a63 100644 --- a/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs @@ -395,7 +395,7 @@ public void IsGenericMethodDefinition(MockTarget.Architecture arch) MethodDescHandle handle = rts.GetMethodDescHandle(genericMethodDef); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(rts.IsGenericMethodDefinition(handle)); - var instantiation = rts.GetGenericMethodInstantiation(handle); + ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); Assert.Equal(0, instantiation.Length); } @@ -403,7 +403,7 @@ public void IsGenericMethodDefinition(MockTarget.Architecture arch) MethodDescHandle handle = rts.GetMethodDescHandle(genericWithInst); Assert.NotEqual(TargetPointer.Null, handle.Address); Assert.True(rts.IsGenericMethodDefinition(handle)); - var instantiation = rts.GetGenericMethodInstantiation(handle); + ReadOnlySpan instantiation = rts.GetGenericMethodInstantiation(handle); Assert.Equal(typeArgsRawAddrs.Length, instantiation.Length); for (int i = 0; i < typeArgsRawAddrs.Length; i++) { From 8f8f9b003d9051a0932fb52460c82573f1afe2c2 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Thu, 16 Jul 2026 13:25:31 -0400 Subject: [PATCH 15/23] Default ArgumentLocation handles to the null sentinel Use an explicit struct constructor with ITypeHandle.Null property initializers so object initializers that omit TypeHandle or OpenGenericType preserve the old zero-valued TypeHandle semantics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../Contracts/CallingConvention/ArgumentLocation.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs index 25f3f962cdfe83..a523a023ea37d6 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs @@ -7,9 +7,13 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal readonly struct ArgumentLocation { + public ArgumentLocation() + { + } + public int Offset { get; init; } public CorElementType ElementType { get; init; } - public ITypeHandle TypeHandle { get; init; } + public ITypeHandle TypeHandle { get; init; } = ITypeHandle.Null; public bool IsThis { get; init; } public bool IsValueTypeThis { get; init; } public bool IsParamType { get; init; } @@ -30,7 +34,7 @@ internal readonly struct ArgumentLocation // For generic-instantiation parameters with an uncached closed ITypeHandle, // the open generic MethodTable (e.g. Span for a Span arg) so // encoders can inspect type structure as a fallback. - public ITypeHandle OpenGenericType { get; init; } + public ITypeHandle OpenGenericType { get; init; } = ITypeHandle.Null; // SystemV-AMD64 struct passed in registers. Offset is the StructInRegsOffset // sentinel; the encoder consumes SysVEightByteDescriptor + SysVIdxGenReg. From a72c6139181d703b63c8b52a70238a8f45f1748b Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Thu, 16 Jul 2026 17:26:57 -0400 Subject: [PATCH 16/23] Fix typo in RuntimeTypeSystem comment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../Contracts/RuntimeTypeSystem_1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index 36fd09629a2113..16d312382c84c1 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -522,7 +522,7 @@ public ITypeHandle GetTypeHandle(TargetPointer typeHandlePointer) return GetOrCreateTargetTypeHandle(methodTablePointer); } - // Otherwse, get ready to validate + // Otherwise, get ready to validate if (!_typeValidation.TryValidateMethodTablePointer(methodTablePointer)) { throw new ArgumentException("Invalid method table pointer", nameof(typeHandlePointer)); From 2e2d66ccac61e476a2fe5835f86b144ffa920211 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Mon, 20 Jul 2026 13:13:05 -0400 Subject: [PATCH 17/23] Clarify runtime TypeHandle signature encoding Document that ELEMENT_TYPE_INTERNAL and ELEMENT_TYPE_CMOD_INTERNAL contain raw runtime TypeHandle pointers that the provider resolves to cDAC types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../Contracts/Signature/IRuntimeSignatureTypeProvider.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs index 722247e1f4fe1e..b261c7cd0a68d8 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs @@ -21,13 +21,15 @@ public interface IRuntimeSignatureTypeProvider { /// /// Classify an ELEMENT_TYPE_INTERNAL (0x21) type by resolving the - /// embedded ITypeHandle pointer via the target's runtime type system. + /// embedded runtime TypeHandle pointer to a cDAC type through the + /// target's runtime type system. /// TType GetInternalType(TargetPointer typeHandlePointer); /// /// Classify an ELEMENT_TYPE_CMOD_INTERNAL (0x22) custom modifier by - /// resolving the embedded ITypeHandle pointer via the target's runtime type system. + /// resolving the embedded runtime TypeHandle pointer to a cDAC type + /// through the target's runtime type system. /// TType GetInternalModifiedType(TargetPointer typeHandlePointer, TType unmodifiedType, bool isRequired); } From b67eb507941315980630a421ff414da70f75d7e5 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Mon, 20 Jul 2026 16:06:44 -0400 Subject: [PATCH 18/23] Clarify ITypeHandle null sentinel documentation Document that unsupported type parameters return ITypeHandle.Null rather than a null reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../Contracts/IRuntimeTypeSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index 68d668a9aab295..79974c5513062a 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -267,7 +267,7 @@ public interface IRuntimeTypeSystem : IContract bool IsPointer(ITypeHandle typeHandle) => throw new NotImplementedException(); bool IsTypeDesc(ITypeHandle typeHandle) => throw new NotImplementedException(); TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) => throw new NotImplementedException(); - // Returns null if the ITypeHandle is not a class/struct/generic variable + // Returns ITypeHandle.Null if the handle is not a class, struct, or generic variable. #endregion ITypeHandle inspection APIs #region MethodDesc inspection APIs From 6e7f483f15307ad93ca3ae671ced774dae654214 Mon Sep 17 00:00:00 2001 From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com> Date: Mon, 20 Jul 2026 22:52:07 -0400 Subject: [PATCH 19/23] Update docs/design/datacontracts/Signature.md Co-authored-by: Noah Falk --- docs/design/datacontracts/Signature.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/datacontracts/Signature.md b/docs/design/datacontracts/Signature.md index 72507f4b6074c5..a5210a0e990f85 100644 --- a/docs/design/datacontracts/Signature.md +++ b/docs/design/datacontracts/Signature.md @@ -54,7 +54,7 @@ Constants: | `ELEMENT_TYPE_INTERNAL` | runtime-internal element type tag for an internal `TypeHandle` | `0x21` | | `ELEMENT_TYPE_CMOD_INTERNAL` | runtime-internal element type tag for an internal modified type | `0x22` | -Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer to a runtime `TypeHandle` (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a cDAC `ITypeHandle`. +Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer to a runtime `TypeHandle` (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a `ITypeHandle`. The decoder is implemented as `RuntimeSignatureDecoder` -- a clone of SRM's `SignatureDecoder` with added support for the runtime-internal element types. The clone takes an additional `Target` so internal-type pointers can be sized for the target architecture. Provider implementations implement `IRuntimeSignatureTypeProvider` -- a superset of `System.Reflection.Metadata.ISignatureTypeProvider` -- adding methods for the runtime-internal element types: From 20b1574d053375417c11f7cfea48bea74e9ae5b1 Mon Sep 17 00:00:00 2001 From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com> Date: Mon, 20 Jul 2026 22:53:29 -0400 Subject: [PATCH 20/23] Apply suggestions from code review Co-authored-by: Noah Falk --- docs/design/datacontracts/ManagedTypeSource.md | 2 +- docs/design/datacontracts/RuntimeTypeSystem.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/design/datacontracts/ManagedTypeSource.md b/docs/design/datacontracts/ManagedTypeSource.md index e0e62de5d70a87..f6556951bfa421 100644 --- a/docs/design/datacontracts/ManagedTypeSource.md +++ b/docs/design/datacontracts/ManagedTypeSource.md @@ -21,7 +21,7 @@ bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info); // Throws InvalidOperationException if the type cannot be resolved. Target.TypeInfo GetTypeInfo(string fullyQualifiedName); -// Return true and populate `typeHandle` with the cDAC ITypeHandle for the runtime type, +// Return true and populate `typeHandle` with the ITypeHandle for the runtime type, // or false if the type cannot be resolved. bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle); ITypeHandle GetTypeHandle(string fullyQualifiedName); diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index 641006848e0d52..facc2bb018b525 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -35,7 +35,7 @@ internal enum CorElementType } ``` -An `ITypeHandle` is the cDAC representation of runtime type information. Consumers obtain +An `ITypeHandle` is the representation of runtime type information. Consumers obtain canonical handles from `RuntimeTypeSystem.GetTypeHandle` using the target address of a runtime `TypeHandle` or `MethodTable`. From f9066d93faadf6e00ddb445ea12a418add388a02 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Mon, 20 Jul 2026 23:52:36 -0400 Subject: [PATCH 21/23] Use nullable references for absent ITypeHandle values Represent the absence of a type with C# null rather than a non-null sentinel. This removes ITypeHandle.Null, NullTypeHandle, and ITypeHandle.IsNull, and uses nullable annotations to document the APIs and fields where type resolution may fail. - Make constructed/approximate/signature resolution results nullable. - Annotate ManagedTypeSource TryGetTypeHandle with NotNullWhen(true). - Propagate nullable signature types through providers and calling-convention metadata while keeping loaded runtime instantiations non-null. - Update DacDbi/Legacy consumers and dump tests to use is null/is not null. - Update authoritative contract documentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- .../design/datacontracts/ManagedTypeSource.md | 4 +- .../design/datacontracts/RuntimeTypeSystem.md | 25 +++---- docs/design/datacontracts/Signature.md | 8 +- .../Contracts/IManagedTypeSource.cs | 3 +- .../Contracts/IRuntimeTypeSystem.cs | 21 +----- .../Contracts/ISignature.cs | 2 +- .../CallingConvention/ArgumentLocation.cs | 8 +- .../CallingConvention/CallingConvention_1.cs | 52 ++++++------- .../CallingConvention/CdacTypeHandle.cs | 30 ++++---- .../Contracts/ManagedTypeSource_1.cs | 20 ++--- .../TypeHandleImplementations.cs | 1 - .../Contracts/RuntimeTypeSystem_1.cs | 62 +++++++++------- .../Signature/SignatureTypeProvider.cs | 45 ++++++------ .../Contracts/Signature/Signature_1.cs | 14 ++-- .../Dbi/DacDbiImpl.cs | 73 +++++++++---------- .../Dbi/TypeDataWalk.cs | 72 +++++++++--------- .../SOSDacImpl.cs | 4 +- .../SigFormat.cs | 7 +- .../TypeNameBuilder.cs | 14 ++-- .../cdac/gen/TypeNameResolverSource.cs | 2 +- .../cdac/tests/DumpTests/CCWDumpTests.cs | 2 - .../CollectibleGenericInstDumpTests.cs | 7 +- .../DacDbi/DacDbiApproxTypeHandleDumpTests.cs | 46 +++++++----- 23 files changed, 252 insertions(+), 270 deletions(-) diff --git a/docs/design/datacontracts/ManagedTypeSource.md b/docs/design/datacontracts/ManagedTypeSource.md index f6556951bfa421..465f48fd8e6621 100644 --- a/docs/design/datacontracts/ManagedTypeSource.md +++ b/docs/design/datacontracts/ManagedTypeSource.md @@ -23,7 +23,7 @@ Target.TypeInfo GetTypeInfo(string fullyQualifiedName); // Return true and populate `typeHandle` with the ITypeHandle for the runtime type, // or false if the type cannot be resolved. -bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle); +bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle? typeHandle); ITypeHandle GetTypeHandle(string fullyQualifiedName); // Return true and populate `address` with the address of the named static field, @@ -96,7 +96,7 @@ bool TryResolveType(string managedFqName, out ITypeHandle th, out MetadataReader return true; } -bool TryGetTypeHandle(string fqn, out ITypeHandle th) +bool TryGetTypeHandle(string fqn, out ITypeHandle? th) { return TryResolveType(fqn, out th, out _, out _); } diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index facc2bb018b525..7a76e071472190 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -12,13 +12,10 @@ Given a `TargetPointer` address, the `RuntimeTypeSystem` contract provides an `I ``` csharp // An opaque canonical identity for a runtime type. Handles are produced and // interned by RuntimeTypeSystem; consumers must not fabricate implementations. +// A null reference represents the absence of a type. interface ITypeHandle { TargetPointer Address { get; } - bool IsNull { get; } - - // Sentinel handle representing the absence of a type (Address == 0). - static ITypeHandle Null { get; } } // An internal real target-backed handle (a MethodTable* or TypeDesc* address). @@ -145,7 +142,7 @@ partial interface IRuntimeTypeSystem : IContract // return true if the TypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. bool IsArray(ITypeHandle typeHandle, out uint rank); ITypeHandle GetTypeParam(ITypeHandle typeHandle); - ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default); + ITypeHandle? GetConstructedType(ITypeHandle? typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default); ITypeHandle GetPrimitiveType(CorElementType typeCode); bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token); bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv); @@ -322,7 +319,7 @@ bool IsFieldDescStatic(TargetPointer fieldDescPointer); bool IsFieldDescRVA(TargetPointer fieldDescPointer); CorElementType GetFieldDescType(TargetPointer fieldDescPointer); uint GetFieldDescOffset(TargetPointer fieldDescPointer, FieldDefinition? fieldDef); -ITypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer); +ITypeHandle? GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer); bool TryGetFieldDescNext(TargetPointer fieldDescPointer, out TargetPointer nextFieldDesc); TargetPointer GetFieldDescStaticAddress(TargetPointer fieldDescPointer, bool unboxValueTypes = true); TargetPointer GetFieldDescThreadStaticAddress(TargetPointer fieldDescPointer, TargetPointer thread, bool unboxValueTypes = true); @@ -1204,15 +1201,15 @@ Contracts used: return (flags & (uint)MethodTableAuxiliaryFlags.IsNotFullyLoaded) == 0; } - ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) + ITypeHandle? GetConstructedType(ITypeHandle? typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) { // For function pointers the type handle arg is unused - type information is provided in the type arguments. - if (corElementType != CorElementType.FnPtr && typeHandle.Address == TargetPointer.Null) - return ITypeHandle.Null; + if (corElementType != CorElementType.FnPtr && typeHandle is null) + return null; ILoader loaderContract = _target.Contracts.Loader; TargetPointer loaderModule = // see [link](https://github.com/dotnet/runtime/blob/e1979b72ccb5f916649f1d9949ef663254790c25/src/coreclr/vm/clsload.cpp#L78) ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(loaderModule); - ITypeHandle potentialMatch = ITypeHandle.Null; + ITypeHandle? potentialMatch = null; foreach (TargetPointer ptr in loaderContract.GetAvailableTypeParams(moduleHandle)) { potentialMatch = GetTypeHandle(ptr); @@ -1235,7 +1232,7 @@ Contracts used: return potentialMatch; } } - return ITypeHandle.Null; + return null; } public ITypeHandle GetPrimitiveType(CorElementType typeCode) @@ -2353,12 +2350,12 @@ TargetPointer GetFieldDescThreadStaticAddress(TargetPointer fieldDescPointer, Ta // The unboxValueTypes parameter behaves the same as in GetFieldDescStaticAddress. } -ITypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) +ITypeHandle? GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) { // Resolve enclosing MT -> Module -> MetadataReader, decode the field's // signature using the SignatureDecoder contract with a SignatureTypeProvider // bound to the enclosing class as generic context, and return the resulting - // TypeHandle. Returns TypeHandle.Null if any link in the chain is unavailable + // TypeHandle. Returns null if any link in the chain is unavailable // (e.g. uncached constructed instantiation). } @@ -2369,7 +2366,7 @@ bool TryGetFieldDescNext(TargetPointer fieldDescPointer, out TargetPointer nextF // MethodTable) and, if `fieldDescPointer` is the last FieldDesc in that type's list, report that // there is no next FieldDesc by returning false. TargetPointer enclosingMT = GetMTOfEnclosingClass(fieldDescPointer); - TypeHandle typeHandle = GetTypeHandle(enclosingMT); + ITypeHandle typeHandle = GetTypeHandle(enclosingMT); // The field list holds the type's own instance fields (total instance fields minus the parent's) // followed by its static fields; see GetFieldDescList. TargetPointer lastFieldDesc = /* address of the final FieldDesc in typeHandle's list */; diff --git a/docs/design/datacontracts/Signature.md b/docs/design/datacontracts/Signature.md index a5210a0e990f85..8265c52950da6a 100644 --- a/docs/design/datacontracts/Signature.md +++ b/docs/design/datacontracts/Signature.md @@ -16,7 +16,7 @@ These tags are used in signatures generated internally by the runtime that are n ## APIs of contract ```csharp -ITypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx); +ITypeHandle? DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle? ctx); // Returns the address of the first argument of a vararg call relative to the cookie pointer location. TargetPointer GetVarArgArgsBase(TargetPointer vaSigCookieAddr); @@ -66,12 +66,12 @@ TType GetInternalModifiedType(TargetPointer typeHandlePointer, TType unmodifiedT The contract's provider resolves these pointers through `RuntimeTypeSystem.GetTypeHandle`. Standard ECMA-335 element types resolve through `RuntimeTypeSystem.GetPrimitiveType` and `RuntimeTypeSystem.GetConstructedType`. Generic type parameters (`VAR`) and generic method parameters (`MVAR`) resolve via `RuntimeTypeSystem.GetInstantiation` and `RuntimeTypeSystem.GetGenericMethodInstantiation` respectively, using an `ITypeHandle` (for generic types) or `MethodDescHandle` (for generic methods) generic context. `GetTypeFromDefinition` and `GetTypeFromReference` resolve tokens via the module's `TypeDefToMethodTableMap` / `TypeRefToMethodTableMap`; cross-module references and `GetTypeFromSpecification` are not currently implemented. ```csharp -ITypeHandle ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) +ITypeHandle? ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle? ctx) { - SignatureTypeProvider provider = new(_target, moduleHandle); + SignatureTypeProvider provider = new(_target, moduleHandle); MetadataReader mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle)!; BlobReader blobReader = mdReader.GetBlobReader(blobHandle); - RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); + RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); return decoder.DecodeFieldSignature(ref blobReader); } ``` diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs index f81568d517512a..16b64a5a659728 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.Diagnostics.DataContractReader.Data; namespace Microsoft.Diagnostics.DataContractReader.Contracts; @@ -16,7 +17,7 @@ public interface IManagedTypeSource : IContract bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info) => throw new NotImplementedException(); Target.TypeInfo GetTypeInfo(string fullyQualifiedName) => throw new NotImplementedException(); - bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle) => throw new NotImplementedException(); + bool TryGetTypeHandle(string fullyQualifiedName, [NotNullWhen(true)] out ITypeHandle? typeHandle) => throw new NotImplementedException(); ITypeHandle GetTypeHandle(string fullyQualifiedName) => throw new NotImplementedException(); bool TryGetStaticFieldAddress(string fullyQualifiedName, string fieldName, out TargetPointer address) => throw new NotImplementedException(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index 79974c5513062a..e5dd64fd005a3e 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -15,22 +15,6 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; public interface ITypeHandle { TargetPointer Address { get; } - bool IsNull { get; } - - /// Sentinel handle representing the absence of a type. - static ITypeHandle Null => NullTypeHandle.Instance; -} - -/// -/// Singleton ITypeHandle representing the absence of a type. Exposed only through -/// ; the concrete type is an implementation detail. -/// -internal sealed class NullTypeHandle : ITypeHandle -{ - public static readonly NullTypeHandle Instance = new(); - private NullTypeHandle() { } - public TargetPointer Address => TargetPointer.Null; - public bool IsNull => true; } public enum CorElementType @@ -260,14 +244,13 @@ public interface IRuntimeTypeSystem : IContract // return true if the ITypeHandle represents an array, and set the rank to either 0 (if the type is not an array), or the rank number if it is. bool IsArray(ITypeHandle typeHandle, out uint rank) => throw new NotImplementedException(); ITypeHandle GetTypeParam(ITypeHandle typeHandle) => throw new NotImplementedException(); - ITypeHandle GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default) => throw new NotImplementedException(); + ITypeHandle? GetConstructedType(ITypeHandle? typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv = SignatureCallingConvention.Default) => throw new NotImplementedException(); ITypeHandle GetPrimitiveType(CorElementType typeCode) => throw new NotImplementedException(); bool IsGenericVariable(ITypeHandle typeHandle, out TargetPointer module, out uint token) => throw new NotImplementedException(); bool IsFunctionPointer(ITypeHandle typeHandle, out ReadOnlySpan retAndArgTypes, out SignatureCallingConvention callConv) => throw new NotImplementedException(); bool IsPointer(ITypeHandle typeHandle) => throw new NotImplementedException(); bool IsTypeDesc(ITypeHandle typeHandle) => throw new NotImplementedException(); TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) => throw new NotImplementedException(); - // Returns ITypeHandle.Null if the handle is not a class, struct, or generic variable. #endregion ITypeHandle inspection APIs #region MethodDesc inspection APIs @@ -347,7 +330,7 @@ public interface IRuntimeTypeSystem : IContract bool IsFieldDescRVA(TargetPointer fieldDescPointer) => throw new NotImplementedException(); CorElementType GetFieldDescType(TargetPointer fieldDescPointer) => throw new NotImplementedException(); uint GetFieldDescOffset(TargetPointer fieldDescPointer, FieldDefinition? fieldDef) => throw new NotImplementedException(); - ITypeHandle GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) => throw new NotImplementedException(); + ITypeHandle? GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) => throw new NotImplementedException(); bool TryGetFieldDescNext(TargetPointer fieldDescPointer, out TargetPointer nextFieldDesc) => throw new NotImplementedException(); TargetPointer GetFieldDescByName(ITypeHandle typeHandle, string fieldName) => throw new NotImplementedException(); TargetPointer GetFieldDescStaticAddress(TargetPointer fieldDescPointer, bool unboxValueTypes = true) => throw new NotImplementedException(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs index f07ed2b07ad8c9..a1412a655fb324 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs @@ -9,7 +9,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; public interface ISignature : IContract { static string IContract.Name { get; } = nameof(Signature); - ITypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) => throw new NotImplementedException(); + ITypeHandle? DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle? ctx) => throw new NotImplementedException(); TargetPointer GetVarArgArgsBase(TargetPointer vaSigCookieAddr) => throw new NotImplementedException(); void GetVarArgSignature(TargetPointer vaSigCookieAddr, out TargetPointer signatureAddress, out uint signatureLength) => throw new NotImplementedException(); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs index a523a023ea37d6..46f79b2cb81a68 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs @@ -7,13 +7,9 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal readonly struct ArgumentLocation { - public ArgumentLocation() - { - } - public int Offset { get; init; } public CorElementType ElementType { get; init; } - public ITypeHandle TypeHandle { get; init; } = ITypeHandle.Null; + public ITypeHandle? TypeHandle { get; init; } public bool IsThis { get; init; } public bool IsValueTypeThis { get; init; } public bool IsParamType { get; init; } @@ -34,7 +30,7 @@ public ArgumentLocation() // For generic-instantiation parameters with an uncached closed ITypeHandle, // the open generic MethodTable (e.g. Span for a Span arg) so // encoders can inspect type structure as a fallback. - public ITypeHandle OpenGenericType { get; init; } = ITypeHandle.Null; + public ITypeHandle? OpenGenericType { get; init; } // SystemV-AMD64 struct passed in registers. Offset is the StructInRegsOffset // sentinel; the encoder consumes SysVEightByteDescriptor + SysVIdxGenReg. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs index 8c2a3c6c78c9ae..44f83df6692e91 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CallingConvention_1.cs @@ -76,7 +76,7 @@ private readonly struct ParamTypeInfo // (e.g. Span for a Span arg). Used by the encoder when the // constructed ITypeHandle is null (uncached) to fall back to // attributes of the open type (IsByRefLike, etc.). - public ITypeHandle OpenGenericType { get; init; } + public ITypeHandle? OpenGenericType { get; init; } } private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) @@ -84,7 +84,7 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; IRuntimeInfo runtimeInfo = _target.Contracts.RuntimeInfo; - MethodSignature methodSig = DecodeMethodSignature(rts, methodDesc); + MethodSignature methodSig = DecodeMethodSignature(rts, methodDesc); // Re-decode the same signature with a wrapper provider to learn each // parameter's outermost element type (Byref / Ptr / SzArray / Array) @@ -218,7 +218,9 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) } else { - elemType = rts.GetSignatureCorElementType(methodSig.ParameterTypes[argIndex]); + elemType = methodSig.ParameterTypes[argIndex] is ITypeHandle parameterType + ? rts.GetSignatureCorElementType(parameterType) + : default; } if (argOffset == TransitionBlock.StructInRegsOffset) @@ -256,10 +258,9 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) bool isByRefLikeStruct = false; if (elemType == CdacCorElementType.ValueType && !passedByRef) { - ITypeHandle probe = methodSig.ParameterTypes[argIndex]; - if (probe.Address == TargetPointer.Null) - probe = paramInfo[argIndex].OpenGenericType; - if (probe.Address != TargetPointer.Null) + ITypeHandle? probe = methodSig.ParameterTypes[argIndex]; + probe ??= paramInfo[argIndex].OpenGenericType; + if (probe is not null) { try { isByRefLikeStruct = rts.IsByRefLike(probe); } catch { /* leave false on partial-state failures */ } @@ -287,7 +288,7 @@ private ArgumentLayout GetArgumentLayout(MethodDescHandle methodDesc) return new ArgumentLayout(arguments, cbStackPop); } - private MethodSignature DecodeMethodSignature( + private MethodSignature DecodeMethodSignature( IRuntimeTypeSystem rts, MethodDescHandle methodDesc) { TargetPointer methodTablePtr = rts.GetMethodTable(methodDesc); @@ -305,7 +306,7 @@ private MethodSignature DecodeMethodSignature( // NotSupportedException for whichever side it wasn't parameterized on. MethodSigContext context = new(methodDesc, typeHandle); MethodAndTypeContextProvider provider = new(_target, moduleHandle, rts); - RuntimeSignatureDecoder decoder = new( + RuntimeSignatureDecoder decoder = new( provider, _target, mdReader, context); if (!rts.TryGetMethodSignature(methodDesc, out ReadOnlySpan methodSig)) @@ -420,7 +421,7 @@ private CdacTypeHandle GetIntPtrTypeHandle(IRuntimeTypeSystem rts) // hasn't cached the constructed-type instantiation. private readonly struct TrackedType { - public ITypeHandle Underlying { get; init; } + public ITypeHandle? Underlying { get; init; } public bool IsByRef { get; init; } // The outermost ELEMENT_TYPE_* wrapper applied to this signature. // The enum's zero value (default) means "no constructed-type wrapper; @@ -430,7 +431,7 @@ private readonly struct TrackedType // GetConstructedType collapsed it. Lets the encoder inspect // attributes (IsByRefLike, etc.) even when the constructed // ITypeHandle isn't cached. - public ITypeHandle OpenGeneric { get; init; } + public ITypeHandle? OpenGeneric { get; init; } } // ISignatureTypeProvider wrapper that records the outermost @@ -456,7 +457,7 @@ public ParamMetadataProvider(MethodAndTypeContextProvider inner, IRuntimeTypeSys // know to fall back to GetSignatureCorElementType on Underlying. The // constructed-type overrides (ByRef/Ptr/SzArray/Array) set // OutermostKind explicitly. - private static TrackedType Wrap(ITypeHandle th) + private static TrackedType Wrap(ITypeHandle? th) => new() { Underlying = th }; public TrackedType GetByReferenceType(TrackedType elementType) @@ -480,17 +481,17 @@ public TrackedType GetFunctionPointerType(MethodSignature signature public TrackedType GetGenericInstantiation(TrackedType genericType, ImmutableArray typeArguments) { - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(typeArguments.Length); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(typeArguments.Length); for (int i = 0; i < typeArguments.Length; i++) builder.Add(typeArguments[i].Underlying); - ITypeHandle constructed = _inner.GetGenericInstantiation(genericType.Underlying, builder.ToImmutable()); + ITypeHandle? constructed = _inner.GetGenericInstantiation(genericType.Underlying, builder.ToImmutable()); // GetConstructedType returns null when the runtime hasn't cached // this exact instantiation. Recover the would-be top-level kind // (Class / ValueType / ...) from the open generic type so the // encoder still sees the right token (REF for class, etc.). CdacCorElementType kind = default; - if (constructed.Address == TargetPointer.Null && genericType.Underlying.Address != TargetPointer.Null) + if (constructed is null && genericType.Underlying is not null) { try { kind = _rts.GetSignatureCorElementType(genericType.Underlying); } catch { /* leave default */ } @@ -563,7 +564,7 @@ public TrackedType GetInternalModifiedType(TargetPointer typeHandlePointer, Trac // methods without making the base virtual. internal sealed class MethodAndTypeContextProvider : SignatureTypeProvider, - IRuntimeSignatureTypeProvider + IRuntimeSignatureTypeProvider { private readonly IRuntimeTypeSystem _rts; @@ -573,10 +574,10 @@ public MethodAndTypeContextProvider(Target target, ModuleHandle moduleHandle, IR _rts = rts; } - public new ITypeHandle GetGenericMethodParameter(MethodSigContext context, int index) + public new ITypeHandle? GetGenericMethodParameter(MethodSigContext context, int index) => _rts.GetGenericMethodInstantiation(context.Method)[index]; - public new ITypeHandle GetGenericTypeParameter(MethodSigContext context, int index) + public new ITypeHandle? GetGenericTypeParameter(MethodSigContext context, int index) => _rts.GetInstantiation(context.OwningType)[index]; } @@ -702,17 +703,16 @@ public MethodAndTypeContextProvider(Target target, ModuleHandle moduleHandle, IR // The byref/ptr distinction is preserved at the // FieldDesc level regardless of which T closes // the type. - ITypeHandle probe = arg.TypeHandle; - if (probe.Address == TargetPointer.Null) - probe = arg.OpenGenericType; - if (probe.Address != TargetPointer.Null) + ITypeHandle? probe = arg.TypeHandle; + probe ??= arg.OpenGenericType; + if (probe is not null) { EmitByRefLikeInterior(rts, probe, arg.Offset, tokens); } emitted = true; } - if (rts.ContainsGCPointers(arg.TypeHandle)) + if (arg.TypeHandle is ITypeHandle typeHandle && rts.ContainsGCPointers(typeHandle)) { // By-value struct with embedded GC pointers: emit one // Ref token per pointer slot inside the struct. Mirrors @@ -722,7 +722,7 @@ public MethodAndTypeContextProvider(Target target, ModuleHandle moduleHandle, IR // pointer); subtract pointerSize to translate to the // unboxed in-frame layout. int structFieldStart = arg.Offset - pointerSize; - foreach ((uint seriesOffset, uint seriesSize) in rts.GetGCDescSeries(arg.TypeHandle)) + foreach ((uint seriesOffset, uint seriesSize) in rts.GetGCDescSeries(typeHandle)) { int seriesBase = structFieldStart + (int)seriesOffset; for (int subOff = 0; subOff < (int)seriesSize; subOff += pointerSize) @@ -910,8 +910,8 @@ private static void EmitByRefLikeInteriorRecursive( // Nested value-type field. Recurse only if the field's own // MethodTable is ByRefLike (matches runtime Find(FieldDesc*) // in ByRefPointerOffsetsReporter). - ITypeHandle nested = rts.GetFieldDescApproxTypeHandle(fdPtr); - if (nested.Address == TargetPointer.Null) + ITypeHandle? nested = rts.GetFieldDescApproxTypeHandle(fdPtr); + if (nested is null) continue; bool nestedByRefLike; try { nestedByRefLike = rts.IsByRefLike(nested); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs index bad1d3bc8aa79b..1747dadf8e8282 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/CdacTypeHandle.cs @@ -18,7 +18,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; /// internal readonly struct CdacTypeHandle : Internal.CallingConvention.ITypeHandle { - private readonly CdacITypeHandle _typeHandle; + private readonly CdacITypeHandle? _typeHandle; private readonly Target _target; // Outermost ELEMENT_TYPE_* wrapper (PTR / BYREF / SZARRAY / ARRAY / etc.) @@ -31,12 +31,12 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers; // "no override; ask Rts". private readonly CdacCorElementType _kindOverride; - public CdacTypeHandle(CdacITypeHandle typeHandle, Target target) + public CdacTypeHandle(CdacITypeHandle? typeHandle, Target target) : this(typeHandle, target, kindOverride: default) { } - public CdacTypeHandle(CdacITypeHandle typeHandle, Target target, CdacCorElementType kindOverride) + public CdacTypeHandle(CdacITypeHandle? typeHandle, Target target, CdacCorElementType kindOverride) { _typeHandle = typeHandle; _target = target; @@ -48,13 +48,13 @@ public CdacTypeHandle(CdacITypeHandle typeHandle, Target target, CdacCorElementT public int PointerSize => _target.PointerSize; public RuntimeInfoArchitecture Arch => _target.Contracts.RuntimeInfo.GetTargetArchitecture(); - public bool IsNull() => _typeHandle.IsNull && _kindOverride == default; + public bool IsNull() => _typeHandle is null && _kindOverride == default; - public bool IsValueType() => !_typeHandle.IsNull && Rts.IsValueType(_typeHandle); + public bool IsValueType() => _typeHandle is not null && Rts.IsValueType(_typeHandle); public bool IsPointerType() => _kindOverride == CdacCorElementType.Ptr - || (!_typeHandle.IsNull && Rts.IsPointer(_typeHandle)); + || (_typeHandle is not null && Rts.IsPointer(_typeHandle)); public bool HasIndeterminateSize() => false; @@ -73,7 +73,7 @@ or CdacCorElementType.SzArray return PointerSize; } - if (_typeHandle.IsNull) + if (_typeHandle is null) return 0; // GetBaseSize returns the full object size including object header and padding. @@ -89,7 +89,7 @@ public SharedCorElementType GetCorElementType() if (_kindOverride != default) return MapCorElementType(_kindOverride); - if (_typeHandle.IsNull) + if (_typeHandle is null) return (SharedCorElementType)0; // Mirror the runtime's MetaSig::PeekArgNormalized -- for value types @@ -108,16 +108,16 @@ public SharedCorElementType GetCorElementType() public bool RequiresAlign8() { - return !_typeHandle.IsNull && Rts.RequiresAlign8(_typeHandle); + return _typeHandle is not null && Rts.RequiresAlign8(_typeHandle); } public bool IsHomogeneousAggregate() - => !_typeHandle.IsNull && Rts.TryGetHFAElementSize(_typeHandle, out _); + => _typeHandle is not null && Rts.TryGetHFAElementSize(_typeHandle, out _); public int GetHomogeneousAggregateElementSize() { Debug.Assert(IsHomogeneousAggregate()); - return Rts.TryGetHFAElementSize(_typeHandle, out int size) ? size : 0; + return Rts.TryGetHFAElementSize(_typeHandle!, out int size) ? size : 0; } public void GetSystemVAmd64PassStructInRegisterDescriptor(out SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR descriptor) @@ -125,7 +125,7 @@ public void GetSystemVAmd64PassStructInRegisterDescriptor(out SYSTEMV_AMD64_CORI descriptor = default; descriptor.passedInRegisters = false; - if (_typeHandle.IsNull) + if (_typeHandle is null) return; // Read the runtime-cached classification from the type system; mirrors @@ -175,7 +175,7 @@ public bool IsTrivialPointerSizedStruct() // Only meaningful on x86 -- this controls whether a value-type arg // can be passed in a register. Outside x86 (where structs always go // through other paths) we return false so callers ignore us. - if (Arch != RuntimeInfoArchitecture.X86 || _typeHandle.IsNull || !Rts.IsValueType(_typeHandle)) + if (Arch != RuntimeInfoArchitecture.X86 || _typeHandle is null || !Rts.IsValueType(_typeHandle)) return false; // Must be exactly pointer-size (4 bytes on x86). @@ -219,8 +219,8 @@ public bool IsTrivialPointerSizedStruct() // pointer-sized struct, we are too. Resolve the field's // ITypeHandle via the field's metadata signature and // re-run IsTrivialPointerSizedStruct on it. - CdacITypeHandle nested = Rts.GetFieldDescApproxTypeHandle(singleFieldType.Value); - if (nested.IsNull) + CdacITypeHandle? nested = Rts.GetFieldDescApproxTypeHandle(singleFieldType.Value); + if (nested is null) return false; return new CdacTypeHandle(nested, _target).IsTrivialPointerSizedStruct(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs index 212138e8d07c2e..1e9c8709260f39 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs @@ -14,7 +14,7 @@ internal sealed class ManagedTypeSource_1 : IManagedTypeSource { private readonly Target _target; private readonly Dictionary _typeInfoCache = new(); - private readonly Dictionary _typeHandleCache = new(); + private readonly Dictionary _typeHandleCache = new(); private readonly Dictionary<(string Fqn, string FieldName), TargetPointer> _fieldDescCache = new(); private bool _inSearch; @@ -87,24 +87,24 @@ public bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info) public ITypeHandle GetTypeHandle(string fullyQualifiedName) { - if (!TryGetTypeHandle(fullyQualifiedName, out ITypeHandle typeHandle)) + if (!TryGetTypeHandle(fullyQualifiedName, out ITypeHandle? typeHandle)) throw new InvalidOperationException($"Managed type '{fullyQualifiedName}' is not resolvable through {nameof(ManagedTypeSource_1)}."); return typeHandle; } - public bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle) + public bool TryGetTypeHandle(string fullyQualifiedName, [NotNullWhen(true)] out ITypeHandle? typeHandle) { if (_typeHandleCache.TryGetValue(fullyQualifiedName, out ITypeHandle? cached)) { typeHandle = cached; - return !typeHandle.IsNull; + return typeHandle is not null; } if (!TryResolveType(fullyQualifiedName, out typeHandle, out _, out _)) { - typeHandle = ITypeHandle.Null; - _typeHandleCache[fullyQualifiedName] = ITypeHandle.Null; + typeHandle = null; + _typeHandleCache[fullyQualifiedName] = null; return false; } @@ -190,7 +190,7 @@ private bool TryGetFieldDesc(string fullyQualifiedName, string fieldName, out Ta if (_fieldDescCache.TryGetValue(key, out fieldDescAddr)) return fieldDescAddr != TargetPointer.Null; - if (!TryResolveType(fullyQualifiedName, out ITypeHandle th, out _, out _)) + if (!TryResolveType(fullyQualifiedName, out ITypeHandle? th, out _, out _)) { fieldDescAddr = TargetPointer.Null; _fieldDescCache[key] = TargetPointer.Null; @@ -206,7 +206,7 @@ private bool TryBuildTypeInfo(string managedFqName, out Target.TypeInfo info) { info = default; - if (!TryResolveType(managedFqName, out ITypeHandle th, out MetadataReader? mdReader, out TypeDefinition typeDef)) + if (!TryResolveType(managedFqName, out ITypeHandle? th, out MetadataReader? mdReader, out TypeDefinition typeDef)) return false; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; @@ -254,9 +254,9 @@ private bool TryBuildTypeInfo(string managedFqName, out Target.TypeInfo info) return true; } - private bool TryResolveType(string managedFqName, out ITypeHandle th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef) + private bool TryResolveType(string managedFqName, [NotNullWhen(true)] out ITypeHandle? th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef) { - th = ITypeHandle.Null; + th = null; typeDef = default; ILoader loader = _target.Contracts.Loader; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs index e959bdc5cc693f..39a319171c8892 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs @@ -15,5 +15,4 @@ internal TargetTypeHandle(TargetPointer address) } public TargetPointer Address { get; } - public bool IsNull => Address == TargetPointer.Null; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index 16d312382c84c1..0adabab8200480 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -89,7 +89,7 @@ internal MethodTable(Data.MethodTable data) private readonly struct TypeKey : IEquatable { - public TypeKey(ITypeHandle typeHandle, CorElementType elementType, int rank, ImmutableArray typeArgs, SignatureCallingConvention callConv = SignatureCallingConvention.Default) + public TypeKey(ITypeHandle? typeHandle, CorElementType elementType, int rank, ImmutableArray typeArgs, SignatureCallingConvention callConv = SignatureCallingConvention.Default) { TypeHandle = typeHandle; ElementType = elementType; @@ -97,10 +97,10 @@ public TypeKey(ITypeHandle typeHandle, CorElementType elementType, int rank, Imm TypeArgs = typeArgs; CallConv = callConv; } - public ITypeHandle TypeHandle { get; } + public ITypeHandle? TypeHandle { get; } public CorElementType ElementType { get; } public int Rank { get; } - public ImmutableArray TypeArgs { get; } + public ImmutableArray TypeArgs { get; } public SignatureCallingConvention CallConv { get; } public bool Equals(TypeKey other) @@ -119,10 +119,11 @@ public bool Equals(TypeKey other) public override int GetHashCode() { - int hash = HashCode.Combine(RuntimeHelpers.GetHashCode(TypeHandle), (int)ElementType, Rank, (int)CallConv); - foreach (ITypeHandle th in TypeArgs) + int typeHandleHash = TypeHandle is null ? 0 : RuntimeHelpers.GetHashCode(TypeHandle); + int hash = HashCode.Combine(typeHandleHash, (int)ElementType, Rank, (int)CallConv); + foreach (ITypeHandle? th in TypeArgs) { - hash = HashCode.Combine(hash, RuntimeHelpers.GetHashCode(th)); + hash = HashCode.Combine(hash, th is null ? 0 : RuntimeHelpers.GetHashCode(th)); } return hash; } @@ -721,9 +722,10 @@ public bool TryGetHFAElementSize(ITypeHandle typeHandle, out int elementSize) elementSize = 8; return true; case CorElementType.ValueType: - current = ((IRuntimeTypeSystem)this).GetFieldDescApproxTypeHandle(firstField); - if (current.IsNull) + ITypeHandle? next = ((IRuntimeTypeSystem)this).GetFieldDescApproxTypeHandle(firstField); + if (next is null) return false; + current = next; continue; default: return false; @@ -1255,7 +1257,7 @@ private ITypeHandle GetRootTypeParam(ITypeHandle typeHandle) return current; } - private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle potentialMatch, ImmutableArray typeArguments) + private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle potentialMatch, ImmutableArray typeArguments) { ReadOnlySpan instantiation = GetInstantiation(potentialMatch); if (instantiation.Length != typeArguments.Length) @@ -1269,7 +1271,7 @@ private bool GenericInstantiationMatch(ITypeHandle genericType, ITypeHandle pote for (int i = 0; i < instantiation.Length; i++) { - if (!(instantiation[i].Address == typeArguments[i].Address)) + if (typeArguments[i] is not ITypeHandle typeArgument || instantiation[i].Address != typeArgument.Address) return false; } return true; @@ -1285,7 +1287,7 @@ private bool ArrayPtrMatch(ITypeHandle elementType, CorElementType corElementTyp } - private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) + private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAndArgTypes, SignatureCallingConvention callConv) { if (!IsFunctionPointer(candidate, out ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) return false; @@ -1295,7 +1297,7 @@ private bool FnPtrMatch(ITypeHandle candidate, ImmutableArray retAn return false; for (int i = 0; i < candidateRetAndArgs.Length; i++) { - if (candidateRetAndArgs[i].Address != retAndArgTypes[i].Address) + if (retAndArgTypes[i] is not ITypeHandle retOrArgType || candidateRetAndArgs[i].Address != retOrArgType.Address) return false; } return true; @@ -1316,10 +1318,15 @@ private bool IsLoaded(ITypeHandle typeHandle) return (auxData.Flags & (uint)MethodTableAuxiliaryFlags.IsNotFullyLoaded) == 0; // IsUnloaded } - ITypeHandle IRuntimeTypeSystem.GetConstructedType(ITypeHandle typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) + ITypeHandle? IRuntimeTypeSystem.GetConstructedType(ITypeHandle? typeHandle, CorElementType corElementType, int rank, ImmutableArray typeArguments, SignatureCallingConvention callConv) { - if (typeHandle.IsNull && corElementType != CorElementType.FnPtr) - return ITypeHandle.Null; + if (typeHandle is null && corElementType != CorElementType.FnPtr) + return null; + foreach (ITypeHandle? typeArgument in typeArguments) + { + if (typeArgument is null) + return null; + } if (_typeHandles.TryGetValue(new TypeKey(typeHandle, corElementType, rank, typeArguments, callConv), out ITypeHandle? existing) && existing is not null) return existing; ILoader loaderContract = _target.Contracts.Loader; @@ -1327,9 +1334,9 @@ ITypeHandle IRuntimeTypeSystem.GetConstructedType(ITypeHandle typeHandle, CorEle if (corElementType == CorElementType.FnPtr) loaderModule = ComputeLoaderModule(TargetPointer.Null, typeArguments); else if (corElementType == CorElementType.GenericInst) - loaderModule = ComputeLoaderModule(GetModule(typeHandle), typeArguments); + loaderModule = ComputeLoaderModule(GetModule(typeHandle!), typeArguments); else - loaderModule = GetLoaderModule(typeHandle); + loaderModule = GetLoaderModule(typeHandle!); ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(loaderModule); ITypeHandle potentialMatch; @@ -1338,7 +1345,7 @@ ITypeHandle IRuntimeTypeSystem.GetConstructedType(ITypeHandle typeHandle, CorEle potentialMatch = GetTypeHandle(ptr); if (corElementType == CorElementType.GenericInst) { - if (GenericInstantiationMatch(typeHandle, potentialMatch, typeArguments) && IsLoaded(potentialMatch)) + if (GenericInstantiationMatch(typeHandle!, potentialMatch, typeArguments) && IsLoaded(potentialMatch)) { _ = _typeHandles.TryAdd(new TypeKey(typeHandle, corElementType, rank, typeArguments), potentialMatch); return potentialMatch; @@ -1352,17 +1359,17 @@ ITypeHandle IRuntimeTypeSystem.GetConstructedType(ITypeHandle typeHandle, CorEle return potentialMatch; } } - else if (ArrayPtrMatch(typeHandle, corElementType, rank, potentialMatch) && IsLoaded(potentialMatch)) + else if (ArrayPtrMatch(typeHandle!, corElementType, rank, potentialMatch) && IsLoaded(potentialMatch)) { _ = _typeHandles.TryAdd(new TypeKey(typeHandle, corElementType, rank, typeArguments), potentialMatch); return potentialMatch; } } - return ITypeHandle.Null; + return null; } // See https://github.com/dotnet/runtime/blob/e1979b72ccb5f916649f1d9949ef663254790c25/src/coreclr/vm/clsload.cpp#L78 - private TargetPointer ComputeLoaderModule(TargetPointer definitionModule, ImmutableArray inst) + private TargetPointer ComputeLoaderModule(TargetPointer definitionModule, ImmutableArray inst) { ILoader loaderContract = _target.Contracts.Loader; TargetPointer latestLoaderModule = TargetPointer.Null; @@ -1377,8 +1384,9 @@ private TargetPointer ComputeLoaderModule(TargetPointer definitionModule, Immuta } bool anyCollectible = false; - foreach (ITypeHandle arg in inst) + foreach (ITypeHandle? nullableArg in inst) { + ITypeHandle arg = nullableArg!; if (arg.Address == TargetPointer.Null) continue; @@ -2355,22 +2363,22 @@ uint IRuntimeTypeSystem.GetFieldDescOffset(TargetPointer fieldDescPointer, Field return offset; } - ITypeHandle IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) + ITypeHandle? IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldDescPointer) { try { TargetPointer enclosingMT = ((IRuntimeTypeSystem)this).GetMTOfEnclosingClass(fieldDescPointer); if (enclosingMT == TargetPointer.Null) - return ITypeHandle.Null; + return null; ITypeHandle enclosingType = GetTypeHandle(enclosingMT); TargetPointer modulePtr = GetModule(enclosingType); if (modulePtr == TargetPointer.Null) - return ITypeHandle.Null; + return null; ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); MetadataReader? mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle); if (mdReader is null) - return ITypeHandle.Null; + return null; uint memberDef = ((IRuntimeTypeSystem)this).GetFieldDescMemberDef(fieldDescPointer); FieldDefinitionHandle fieldDefHandle = (FieldDefinitionHandle)MetadataTokens.Handle((int)memberDef); @@ -2380,7 +2388,7 @@ ITypeHandle IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldD } catch { - return ITypeHandle.Null; + return null; } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs index 813c9466bbd3d9..1f10f401710ca3 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs @@ -10,7 +10,7 @@ namespace Microsoft.Diagnostics.DataContractReader.SignatureHelpers; -public class SignatureTypeProvider : IRuntimeSignatureTypeProvider +public class SignatureTypeProvider : IRuntimeSignatureTypeProvider { private readonly Target _target; private readonly Contracts.ModuleHandle _moduleHandle; @@ -25,19 +25,19 @@ public SignatureTypeProvider(Target target, Contracts.ModuleHandle moduleHandle) _runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; } - public ITypeHandle GetArrayType(ITypeHandle elementType, ArrayShape shape) + public ITypeHandle? GetArrayType(ITypeHandle? elementType, ArrayShape shape) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.Array, shape.Rank, []); - public ITypeHandle GetByReferenceType(ITypeHandle elementType) + public ITypeHandle? GetByReferenceType(ITypeHandle? elementType) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.Byref, 0, []); - public ITypeHandle GetFunctionPointerType(MethodSignature signature) + public ITypeHandle? GetFunctionPointerType(MethodSignature signature) => GetPrimitiveType(PrimitiveTypeCode.IntPtr); - public ITypeHandle GetGenericInstantiation(ITypeHandle genericType, ImmutableArray typeArguments) + public ITypeHandle? GetGenericInstantiation(ITypeHandle? genericType, ImmutableArray typeArguments) => _runtimeTypeSystem.GetConstructedType(genericType, CorElementType.GenericInst, 0, typeArguments); - public ITypeHandle GetGenericMethodParameter(T context, int index) + public ITypeHandle? GetGenericMethodParameter(T context, int index) { if (typeof(T) == typeof(MethodDescHandle)) { @@ -46,55 +46,56 @@ public ITypeHandle GetGenericMethodParameter(T context, int index) } throw new NotSupportedException(); } - public ITypeHandle GetGenericTypeParameter(T context, int index) + public ITypeHandle? GetGenericTypeParameter(T context, int index) { - ITypeHandle typeContext; if (typeof(T) == typeof(ITypeHandle)) { - typeContext = (ITypeHandle)(object)context!; + ITypeHandle? typeContext = (ITypeHandle?)(object?)context; + if (typeContext is null) + return null; return _runtimeTypeSystem.GetInstantiation(typeContext)[index]; } throw new NotImplementedException(); } - public ITypeHandle GetModifiedType(ITypeHandle modifier, ITypeHandle unmodifiedType, bool isRequired) + public ITypeHandle? GetModifiedType(ITypeHandle? modifier, ITypeHandle? unmodifiedType, bool isRequired) => unmodifiedType; - public ITypeHandle GetPinnedType(ITypeHandle elementType) + public ITypeHandle? GetPinnedType(ITypeHandle? elementType) => elementType; - public ITypeHandle GetPointerType(ITypeHandle elementType) + public ITypeHandle? GetPointerType(ITypeHandle? elementType) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.Ptr, 0, []); - public ITypeHandle GetPrimitiveType(PrimitiveTypeCode typeCode) + public ITypeHandle? GetPrimitiveType(PrimitiveTypeCode typeCode) => _runtimeTypeSystem.GetPrimitiveType((CorElementType)typeCode); - public ITypeHandle GetSZArrayType(ITypeHandle elementType) + public ITypeHandle? GetSZArrayType(ITypeHandle? elementType) => _runtimeTypeSystem.GetConstructedType(elementType, CorElementType.SzArray, 1, []); - public ITypeHandle GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) + public ITypeHandle? GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) { int token = MetadataTokens.GetToken((EntityHandle)handle); TargetPointer typeDefToMethodTable = _loader.GetLookupTables(_moduleHandle).TypeDefToMethodTable; TargetPointer typeHandlePtr = _loader.GetModuleLookupMapElement(typeDefToMethodTable, (uint)token, out _); - return typeHandlePtr == TargetPointer.Null ? ITypeHandle.Null : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); + return typeHandlePtr == TargetPointer.Null ? null : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); } - public ITypeHandle GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) + public ITypeHandle? GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) { int token = MetadataTokens.GetToken((EntityHandle)handle); TargetPointer typeRefToMethodTable = _loader.GetLookupTables(_moduleHandle).TypeRefToMethodTable; TargetPointer typeHandlePtr = _loader.GetModuleLookupMapElement(typeRefToMethodTable, (uint)token, out _); - return typeHandlePtr == TargetPointer.Null ? ITypeHandle.Null : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); + return typeHandlePtr == TargetPointer.Null ? null : _runtimeTypeSystem.GetTypeHandle(typeHandlePtr); } - public ITypeHandle GetTypeFromSpecification(MetadataReader reader, T context, TypeSpecificationHandle handle, byte rawTypeKind) + public ITypeHandle? GetTypeFromSpecification(MetadataReader reader, T context, TypeSpecificationHandle handle, byte rawTypeKind) => throw new NotImplementedException(); - public ITypeHandle GetInternalType(TargetPointer typeHandlePointer) + public ITypeHandle? GetInternalType(TargetPointer typeHandlePointer) => typeHandlePointer == TargetPointer.Null - ? ITypeHandle.Null + ? null : _runtimeTypeSystem.GetTypeHandle(typeHandlePointer); - public ITypeHandle GetInternalModifiedType(TargetPointer typeHandlePointer, ITypeHandle unmodifiedType, bool isRequired) + public ITypeHandle? GetInternalModifiedType(TargetPointer typeHandlePointer, ITypeHandle? unmodifiedType, bool isRequired) => unmodifiedType; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs index b3412452ec63d7..7be639ef47fd46 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs @@ -18,7 +18,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; internal sealed class Signature_1 : ISignature { private readonly Target _target; - private readonly Dictionary> _thProviders = []; + private readonly Dictionary> _thProviders = []; internal Signature_1(Target target) { @@ -30,25 +30,25 @@ public void Flush(FlushScope scope) _thProviders.Clear(); } - private SignatureTypeProvider GetTypeHandleProvider(ModuleHandle moduleHandle) + private SignatureTypeProvider GetTypeHandleProvider(ModuleHandle moduleHandle) { - if (_thProviders.TryGetValue(moduleHandle, out SignatureTypeProvider? thProvider)) + if (_thProviders.TryGetValue(moduleHandle, out SignatureTypeProvider? thProvider)) { return thProvider; } - SignatureTypeProvider newProvider = new(_target, moduleHandle); + SignatureTypeProvider newProvider = new(_target, moduleHandle); _thProviders[moduleHandle] = newProvider; return newProvider; } - ITypeHandle ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) + ITypeHandle? ISignature.DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle? ctx) { - SignatureTypeProvider provider = GetTypeHandleProvider(moduleHandle); + SignatureTypeProvider provider = GetTypeHandleProvider(moduleHandle); MetadataReader mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle)!; BlobReader blobReader = mdReader.GetBlobReader(blobHandle); - RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); + RuntimeSignatureDecoder decoder = new(provider, _target, mdReader, ctx); return decoder.DecodeFieldSignature(ref blobReader); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs index d74c3a49cf459c..214f0365a77136 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs @@ -2464,9 +2464,6 @@ public int EnumerateClassFields(ulong thExact, nuint* pObjectSize, delegate* unm IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; ITypeHandle thExactHandle = rts.GetTypeHandle(thExact); // Native semantics: thApprox is the same ITypeHandle that was passed in. - if (thExactHandle.IsNull) - throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; - ITypeHandle thApprox = thExactHandle; // For Generic classes the object size only comes through with an instantiated type. @@ -2520,9 +2517,6 @@ public int EnumerateInstantiationFields(ulong vmAssembly, ulong vmThExact, ulong IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; ITypeHandle thExactHandle = rts.GetTypeHandle(vmThExact); ITypeHandle thApproxHandle = rts.GetTypeHandle(vmThApprox); - if (thApproxHandle.IsNull) - throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; - cdacObjectSize = rts.GetNumInstanceFieldBytes(thApproxHandle); CollectFieldsForDbi(rts, thExactHandle, thApproxHandle, fpCallback, pUserData, cdacFields); @@ -2561,7 +2555,7 @@ private void CollectFieldsForDbi( { TargetPointer gcStaticsBase = TargetPointer.Null; TargetPointer nonGCStaticsBase = TargetPointer.Null; - if (!thExact.IsNull && !rts.IsCollectible(thExact)) + if (!rts.IsCollectible(thExact)) { gcStaticsBase = rts.GetGCStaticsBasePointer(thExact); nonGCStaticsBase = rts.GetNonGCStaticsBasePointer(thExact); @@ -2882,8 +2876,8 @@ public int GetApproxTypeHandle(TypeInfoList* pTypeData, ulong* pRetVal) ITypeHandle canonTh = rts.GetTypeHandle(canonMtPtr); TypeDataWalk walk = new TypeDataWalk(_target, rts, canonTh, pTypeData->m_pList, (uint)pTypeData->m_nEntries); - ITypeHandle th = walk.ReadLoadedTypeHandle(); - if (th.IsNull) + ITypeHandle? th = walk.ReadLoadedTypeHandle(); + if (th is null) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; *pRetVal = th.Address.Value; } @@ -2914,7 +2908,7 @@ public int GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData* pTypeData, ArgInfoL try { IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - ITypeHandle th = ITypeHandle.Null; + ITypeHandle? th = null; CorElementType et = (CorElementType)ReadLittleEndian(pTypeData->elementType); switch (et) { @@ -2937,7 +2931,7 @@ public int GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData* pTypeData, ArgInfoL th = rts.GetPrimitiveType(et); break; } - if (th.Address == TargetPointer.Null) + if (th is null) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; *pVmTypeHandle = th.Address.Value; } @@ -3005,7 +2999,8 @@ private ITypeHandle GetExactArrayTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE ITypeHandle elementType = BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[0]); CorElementType et = (CorElementType)ReadLittleEndian(pTopLevel->elementType); int rank = (int)ReadLittleEndian(pTopLevel->ArrayTypeData_arrayRank); - return rts.GetConstructedType(elementType, et, rank, ImmutableArray.Empty); + return rts.GetConstructedType(elementType, et, rank, ImmutableArray.Empty) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } private ITypeHandle GetExactPtrOrByRefTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) @@ -3014,7 +3009,8 @@ private ITypeHandle GetExactPtrOrByRefTypeHandle(IRuntimeTypeSystem rts, Debugge throw new ArgumentException($"Pointer or byref type with arg count: {pArgInfo->m_nEntries}"); ITypeHandle referent = BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[0]); CorElementType et = (CorElementType)ReadLittleEndian(pTopLevel->elementType); - return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } private ITypeHandle GetExactClassTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE_ExpandedTypeData* pTopLevel, ArgInfoList* pArgInfo) @@ -3027,23 +3023,25 @@ private ITypeHandle GetExactClassTypeHandle(IRuntimeTypeSystem rts, DebuggerIPCE if (argCount == 0) return typeConstructor; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); for (int i = 0; i < argCount; i++) builder.Add(BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[i])); - return rts.GetConstructedType(typeConstructor, CorElementType.GenericInst, 0, builder.MoveToImmutable()); + return rts.GetConstructedType(typeConstructor, CorElementType.GenericInst, 0, builder.MoveToImmutable()) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } private ITypeHandle GetExactFnPtrTypeHandle(IRuntimeTypeSystem rts, ArgInfoList* pArgInfo) { int argCount = pArgInfo->m_nEntries; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(argCount); for (int i = 0; i < argCount; i++) builder.Add(BasicTypeInfoToTypeHandle(rts, &pArgInfo->m_pList[i])); // Non-default calling conventions are not supported. // Currently passes callConv=0 to match native DAC. - return rts.GetConstructedType(ITypeHandle.Null, CorElementType.FnPtr, 0, builder.MoveToImmutable()); + return rts.GetConstructedType(null, CorElementType.FnPtr, 0, builder.MoveToImmutable()) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, uint* pcGenericClassTypeParams, @@ -3102,8 +3100,8 @@ public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, ui // AcquiresInstMethodTableFromThis: token is some MethodTable*; it may be a // subclass, so walk the parent chain to find the exact declaring class. ITypeHandle thFromThis = rts.GetTypeHandle(new TargetPointer(genericsToken)); - ITypeHandle thMatch = GetMethodTableMatchingParentClass(rts, thFromThis, thRepMt); - if (!thMatch.IsNull) + ITypeHandle? thMatch = GetMethodTableMatchingParentClass(rts, thFromThis, thRepMt); + if (thMatch is not null) { thSpecificClass = thMatch; isExact = true; @@ -3126,8 +3124,8 @@ public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, ui // Project the specific class onto the method's declaring class to get the class instantiation. TargetPointer specMethodMtPtr = rts.GetMethodTable(pSpecificMethod); ITypeHandle thSpecMethodMt = rts.GetTypeHandle(specMethodMtPtr); - ITypeHandle thMatchingParent = GetMethodTableMatchingParentClass(rts, thSpecificClass, thSpecMethodMt); - ReadOnlySpan classInst = thMatchingParent.IsNull + ITypeHandle? thMatchingParent = GetMethodTableMatchingParentClass(rts, thSpecificClass, thSpecMethodMt); + ReadOnlySpan classInst = thMatchingParent is null ? default : rts.GetInstantiation(thMatchingParent); ReadOnlySpan methodInst = rts.GetGenericMethodInstantiation(pSpecificMethod); @@ -3355,13 +3353,13 @@ public int GetEnCHangingFieldInfo(EnCHangingFieldInfo* pEnCFieldInfo, FieldData* internal ITypeHandle LookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) { - ITypeHandle th = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); - if (th.IsNull) + ITypeHandle? th = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + if (th is null) throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; return th; } - internal ITypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) + internal ITypeHandle? TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) { ILoader loader = _target.Contracts.Loader; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; @@ -3377,10 +3375,10 @@ internal ITypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint meta mt = loader.GetModuleLookupMapElement(lookupTables.TypeRefToMethodTable, metadataToken, out _); break; default: - return ITypeHandle.Null; + return null; } if (mt == TargetPointer.Null) - return ITypeHandle.Null; + return null; return rts.GetTypeHandle(mt); } @@ -3476,11 +3474,6 @@ public int GetSimpleType(int simpleType, uint* pMetadataToken, ulong* pVmModule) Contracts.IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; ITypeHandle typeHandle = rts.GetPrimitiveType((CorElementType)simpleType); - if (typeHandle.IsNull) - { - throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; - } - Debug.Assert(pMetadataToken != null); *pMetadataToken = rts.GetTypeDefToken(typeHandle); @@ -3856,7 +3849,7 @@ public int GetBasicObjectInfo(ulong objectAddress, Interop.BOOL* pIsValidRef, ui *pObjTypeData = default; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; // verify the object reference is readable and has a valid MethodTable - ITypeHandle th = ITypeHandle.Null; + ITypeHandle? th = null; try { TargetPointer mt = _target.Contracts.Object.GetMethodTableAddress(objectAddress); @@ -3867,7 +3860,7 @@ public int GetBasicObjectInfo(ulong objectAddress, Interop.BOOL* pIsValidRef, ui *pIsValidRef = Interop.BOOL.FALSE; } - if (*pIsValidRef == Interop.BOOL.TRUE) + if (*pIsValidRef == Interop.BOOL.TRUE && th is not null) { // objOffsetToVars = offset from the object base to the first field = sizeof(Object) = pointer size *pObjOffsetToVars = (uint)_target.GetTypeInfo(DataType.Object).Size!.Value; @@ -4784,8 +4777,8 @@ public int GetObjectFields(ulong id, uint celt, COR_FIELD* layout, uint* pceltFe // a null ITypeHandle. try { - ITypeHandle fieldTypeHandle = signature.DecodeFieldSignature(fieldDef.Signature, enclosingModuleHandle, enclosingTypeHandle); - if (fieldTypeHandle.IsNull) + ITypeHandle? fieldTypeHandle = signature.DecodeFieldSignature(fieldDef.Signature, enclosingModuleHandle, enclosingTypeHandle); + if (fieldTypeHandle is null) { corField->id = default; corField->fieldType = 0; @@ -5783,11 +5776,11 @@ private static bool HasSameTypeDefAs(IRuntimeTypeSystem rts, ITypeHandle a, ITyp // Walks the parent chain of `start` and returns the first MethodTable whose TypeDef matches `parent`, // or default if no match is found. The walk is bounded by a hard iteration cap to defend against // cycles observed in corrupt dumps. Mirrors native MethodTable::GetMethodTableMatchingParentClass. - private static ITypeHandle GetMethodTableMatchingParentClass(IRuntimeTypeSystem rts, ITypeHandle start, ITypeHandle parent) + private static ITypeHandle? GetMethodTableMatchingParentClass(IRuntimeTypeSystem rts, ITypeHandle start, ITypeHandle parent) { ITypeHandle current = start; TargetPointer prev = TargetPointer.Null; - for (int i = 0; i < 1000 && !current.IsNull; i++) + for (int i = 0; i < 1000; i++) { if (HasSameTypeDefAs(rts, current, parent)) return current; @@ -5797,7 +5790,7 @@ private static ITypeHandle GetMethodTableMatchingParentClass(IRuntimeTypeSystem prev = current.Address; current = rts.GetTypeHandle(next); } - return ITypeHandle.Null; + return null; } // Shared core implementation for TypeHandleToExpandedTypeInfo and GetObjectExpandedTypeInfo. @@ -5848,9 +5841,9 @@ private void TypeHandleToExpandedTypeInfoImpl(IRuntimeTypeSystem rts, AreValueTy // Determines the CorElementType for a type handle, mapping System.Object and System.String // to their specific element types (the runtime's GetSignatureCorElementType returns E_T_CLASS // for both Object and String). - private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle typeHandle) + private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle? typeHandle) { - if (typeHandle.IsNull) + if (typeHandle is null) return CorElementType.Void; if (rts.IsString(typeHandle)) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs index ec7e2e21377cc1..a33386c22647c9 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs @@ -55,11 +55,11 @@ private void Skip() } } - public ITypeHandle ReadLoadedTypeHandle() + public ITypeHandle? ReadLoadedTypeHandle() { DebuggerIPCE_TypeArgData* p = ReadOne(); if (p == null) - return ITypeHandle.Null; + return null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(p->data.elementType); switch (et) @@ -89,11 +89,11 @@ public ITypeHandle ReadLoadedTypeHandle() } // Read a single type argument in canonicalization-aware fashion. - private ITypeHandle ReadLoadedTypeArg() + private ITypeHandle? ReadLoadedTypeArg() { DebuggerIPCE_TypeArgData* p = ReadOne(); if (p == null) - return ITypeHandle.Null; + return null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(p->data.elementType); switch (et) @@ -114,61 +114,59 @@ private ITypeHandle ReadLoadedTypeArg() } // Read an instantiation and ask the runtime-type-system for the loaded handle. - private ITypeHandle ReadLoadedInstantiation(ulong vmAssembly, uint metadataToken, uint nTypeArgs) + private ITypeHandle? ReadLoadedInstantiation(ulong vmAssembly, uint metadataToken, uint nTypeArgs) { - ITypeHandle typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); - if (typeDef.IsNull) - return ITypeHandle.Null; + ITypeHandle? typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + if (typeDef is null) + return null; if (nTypeArgs == 0) return typeDef; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)nTypeArgs); - bool allOK = true; + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)nTypeArgs); for (uint i = 0; i < nTypeArgs; i++) { - ITypeHandle th = ReadLoadedTypeArg(); - allOK &= !th.IsNull; + ITypeHandle? th = ReadLoadedTypeArg(); + if (th is null) + return null; builder.Add(th); } - if (!allOK) - return ITypeHandle.Null; return _rts.GetConstructedType(typeDef, CorElementType.GenericInst, 0, builder.MoveToImmutable()); } - private ITypeHandle ArrayTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle? ArrayTypeArg(DebuggerIPCE_TypeArgData* pInfo) { - ITypeHandle elem = ReadLoadedTypeArg(); - if (elem.IsNull) - return ITypeHandle.Null; + ITypeHandle? elem = ReadLoadedTypeArg(); + if (elem is null) + return null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(pInfo->data.elementType); int rank = (int)DacDbiImpl.ReadLittleEndian(pInfo->data.ArrayTypeData_arrayRank); - return _rts.GetConstructedType(elem, et, rank, ImmutableArray.Empty); + return _rts.GetConstructedType(elem, et, rank, ImmutableArray.Empty); } - private ITypeHandle PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle? PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData* pInfo) { - ITypeHandle referent = ReadLoadedTypeArg(); - if (referent.IsNull) - return ITypeHandle.Null; + ITypeHandle? referent = ReadLoadedTypeArg(); + if (referent is null) + return null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(pInfo->data.elementType); - return _rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + return _rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } // A generic reference type collapses to System.__Canon // (and its type arguments are skipped); a value-type instantiation is recursively // resolved. - private ITypeHandle ClassTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle? ClassTypeArg(DebuggerIPCE_TypeArgData* pInfo) { ulong vmAssembly = DacDbiImpl.ReadLittleEndian(pInfo->data.ClassTypeData_vmAssembly); uint metadataToken = DacDbiImpl.ReadLittleEndian(pInfo->data.ClassTypeData_metadataToken); uint numTypeArgs = DacDbiImpl.ReadLittleEndian(pInfo->numTypeArgs); CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(pInfo->data.elementType); - ITypeHandle typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + ITypeHandle? typeDef = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); - if ((!typeDef.IsNull && _rts.IsValueType(typeDef)) || et == CorElementType.ValueType) + if ((typeDef is not null && _rts.IsValueType(typeDef)) || et == CorElementType.ValueType) { return ReadLoadedInstantiation(vmAssembly, metadataToken, numTypeArgs); } @@ -180,22 +178,20 @@ private ITypeHandle ClassTypeArg(DebuggerIPCE_TypeArgData* pInfo) } } - private ITypeHandle FnPtrTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle? FnPtrTypeArg(DebuggerIPCE_TypeArgData* pInfo) { uint numTypeArgs = DacDbiImpl.ReadLittleEndian(pInfo->numTypeArgs); - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)numTypeArgs); - bool allOK = true; + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)numTypeArgs); for (uint i = 0; i < numTypeArgs; i++) { - ITypeHandle th = ReadLoadedTypeArg(); - allOK &= !th.IsNull; + ITypeHandle? th = ReadLoadedTypeArg(); + if (th is null) + return null; builder.Add(th); } - if (!allOK) - return ITypeHandle.Null; // Non-default calling conventions are not supported (matches the exact-handle path). - return _rts.GetConstructedType(ITypeHandle.Null, CorElementType.FnPtr, 0, builder.MoveToImmutable()); + return _rts.GetConstructedType(null, CorElementType.FnPtr, 0, builder.MoveToImmutable()); } private ITypeHandle ObjRefOrPrimitiveTypeArg(DebuggerIPCE_TypeArgData* pInfo, CorElementType elementType) @@ -210,7 +206,7 @@ private ITypeHandle ObjRefOrPrimitiveTypeArg(DebuggerIPCE_TypeArgData* pInfo, Co return _rts.GetPrimitiveType(elementType); } - private ITypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) + private ITypeHandle? TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metadataToken) { ILoader loader = _target.Contracts.Loader; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; @@ -226,10 +222,10 @@ private ITypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metad mt = loader.GetModuleLookupMapElement(lookupTables.TypeRefToMethodTable, metadataToken, out _); break; default: - return ITypeHandle.Null; + return null; } if (mt == TargetPointer.Null) - return ITypeHandle.Null; + return null; return rts.GetTypeHandle(mt); } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs index 6aa86a9b85c7f2..ef620a6554aae8 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs @@ -1073,7 +1073,7 @@ int ISOSDacInterface.GetFieldDescData(ClrDataAddress fieldDesc, DacpFieldDescDat MetadataReader mdReader = ecmaMetadataContract.GetMetadata(moduleHandle)!; FieldDefinition fieldDef = mdReader.GetFieldDefinition(fieldHandle); - ITypeHandle foundTypeHandle = rtsContract.GetFieldDescApproxTypeHandle(fieldDescTargetPtr); + ITypeHandle? foundTypeHandle = rtsContract.GetFieldDescApproxTypeHandle(fieldDescTargetPtr); try { // get the MT of the type @@ -1081,7 +1081,7 @@ int ISOSDacInterface.GetFieldDescData(ClrDataAddress fieldDesc, DacpFieldDescDat // that we can return to SOS for pretty-printing. // In the future we may want to return an ITypeHandle instead of a MethodTable, and modify SOS to do more complete pretty-printing. // DAC equivalent: src/coreclr/vm/typehandle.inl TypeHandle::GetMethodTable - if (foundTypeHandle.IsNull) + if (foundTypeHandle is null) // if we can't find the MT (e.g in a minidump) data->MTOfType = 0; else if (rtsContract.IsFunctionPointer(foundTypeHandle, out _, out _) || rtsContract.IsPointer(foundTypeHandle)) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs index a846d3defc1072..0838d6e542991a 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs @@ -308,12 +308,15 @@ private static unsafe void AddTypeString(Target target, } } - private static void AddType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle) + private static void AddType(Target target, StringBuilder stringBuilder, ITypeHandle? typeHandle) { IRuntimeTypeSystem runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; - if (typeHandle.IsNull) + if (typeHandle is null) + { stringBuilder.Append("**UNKNOWN TYPE**"); + return; + } CorElementType corElementType = runtimeTypeSystem.GetSignatureCorElementType(typeHandle); if (corElementType == CorElementType.ValueType && runtimeTypeSystem.HasTypeParam(typeHandle)) { diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs index 89b42c4375f3a1..8dcafeb9f7e585 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs @@ -67,7 +67,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, IRuntimeTypeSystem runtimeTypeSystem = target.Contracts.RuntimeTypeSystem; ILoader loader = target.Contracts.Loader; string methodName; - ITypeHandle th = ITypeHandle.Null; + ITypeHandle? th = null; bool isNoMetadataMethod = runtimeTypeSystem.IsNoMetadataMethod(method, out methodName); if (isNoMetadataMethod) @@ -122,7 +122,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, uint rowId = EcmaMetadataUtils.GetRowId(runtimeTypeSystem.GetMethodToken(method)); if (rowId != 0) { - Contracts.ModuleHandle module = loader.GetModuleHandleFromModulePtr(runtimeTypeSystem.GetModule(th)); + Contracts.ModuleHandle module = loader.GetModuleHandleFromModulePtr(runtimeTypeSystem.GetModule(th!)); MetadataReader reader = target.Contracts.EcmaMetadata.GetMetadata(module)!; MethodDefinition methodDef = reader.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle((int)rowId)); stringBuilder.Append(reader.GetString(methodDef.Name)); @@ -143,7 +143,7 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, MetadataReader? reader = target.Contracts.EcmaMetadata.GetMetadata(methodModule); ReadOnlySpan typeInstantiationSigFormat = default; - if (!th.IsNull) + if (th is not null) { typeInstantiationSigFormat = runtimeTypeSystem.GetInstantiation(th); if (typeInstantiationSigFormat.Length == 0 && runtimeTypeSystem.IsArray(th, out _)) @@ -184,22 +184,22 @@ public static ITypeHandle GetExactOwningType(IRuntimeTypeSystem runtimeTypeSyste } while (true); } - public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle? typeHandle, TypeNameFormat format) { AppendType(target, stringBuilder, typeHandle, default, format); } - public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle typeHandle, ReadOnlySpan typeInstantiation, TypeNameFormat format) + public static void AppendType(Target target, StringBuilder stringBuilder, ITypeHandle? typeHandle, ReadOnlySpan typeInstantiation, TypeNameFormat format) { TypeNameBuilder builder = new(stringBuilder, target, format); AppendTypeCore(ref builder, typeHandle, typeInstantiation, format); } - private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle typeHandle, ReadOnlySpan instantiation, TypeNameFormat format) + private static void AppendTypeCore(ref TypeNameBuilder tnb, ITypeHandle? typeHandle, ReadOnlySpan instantiation, TypeNameFormat format) { bool toString = format.HasFlag(TypeNameFormat.FormatNamespace) && !format.HasFlag(TypeNameFormat.FormatFullInst) && !format.HasFlag(TypeNameFormat.FormatAssembly); - if (typeHandle.IsNull) + if (typeHandle is null) { tnb.AddName("(null)"); } diff --git a/src/native/managed/cdac/gen/TypeNameResolverSource.cs b/src/native/managed/cdac/gen/TypeNameResolverSource.cs index ff4ecb39206db6..1806023ac820a1 100644 --- a/src/native/managed/cdac/gen/TypeNameResolverSource.cs +++ b/src/native/managed/cdac/gen/TypeNameResolverSource.cs @@ -30,7 +30,7 @@ public static ITypeHandle GetTypeHandle(Target target, string[] names) { foreach (string name in names) { - if (target.Contracts.ManagedTypeSource.TryGetTypeHandle(name, out ITypeHandle th)) + if (target.Contracts.ManagedTypeSource.TryGetTypeHandle(name, out ITypeHandle? th)) return th; } throw new InvalidOperationException( diff --git a/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs index 2dec061edbe3d8..c2db5df9492bd1 100644 --- a/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs @@ -96,8 +96,6 @@ public void CCW_InterfaceMethodTablesAreReadable(TestConfiguration config) // Verify the MethodTable is readable by resolving it to an ITypeHandle. ITypeHandle typeHandle = rts.GetTypeHandle(iface.MethodTable); - Assert.False(typeHandle.IsNull, - $"Expected non-null ITypeHandle for MethodTable 0x{iface.MethodTable:X} in CCW 0x{ccwPtr:X}"); Assert.True(rts.GetBaseSize(typeHandle) > 0, $"Expected positive base size for MethodTable 0x{iface.MethodTable:X} in CCW 0x{ccwPtr:X}"); } diff --git a/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs index a7073fcfddc017..851f255f78bcf3 100644 --- a/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/CollectibleGenericInstDumpTests.cs @@ -34,7 +34,7 @@ public void GetConstructedType_ResolvesGenericInstWithCollectibleTypeArgument(Te // Find the List instance rooted by the debuggee. It is the // single-argument generic instantiation whose loader module differs from its // definition module — the signature of a type argument from a collectible ALC. - ITypeHandle constructed = ITypeHandle.Null; + ITypeHandle? constructed = null; foreach (HandleData handle in gc.GetHandles([HandleType.Strong])) { TargetPointer objAddr = Target.ReadPointer(handle.Handle); @@ -51,7 +51,7 @@ public void GetConstructedType_ResolvesGenericInstWithCollectibleTypeArgument(Te } } - Assert.NotEqual(TargetPointer.Null, constructed.Address); + Assert.NotNull(constructed); // Confirm the collectible scenario: the constructed type's loader module is the // collectible argument's module, distinct from its (CoreLib) definition module. @@ -66,12 +66,13 @@ public void GetConstructedType_ResolvesGenericInstWithCollectibleTypeArgument(Te // Reconstruct the instantiation. This must search the collectible argument's // loader module — searching the definition's module (CoreLib) returns null. - ITypeHandle resolved = rts.GetConstructedType( + ITypeHandle? resolved = rts.GetConstructedType( listDefinition, CorElementType.GenericInst, 0, [typeArgument]); + Assert.NotNull(resolved); Assert.Equal(constructed.Address, resolved.Address); } } diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs index 1d76fd8f62a561..a2aa905e690af4 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs @@ -88,8 +88,8 @@ private unsafe void AssertRoundTrip(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITyp // Build the expected canonicalized handle from the exact type. Mirrors the rules // applied by TypeDataWalk on the cDAC side. - ITypeHandle expectedApproxTh = ApproxTopLevel(dbi, rts, canonTh, expectedTh); - if (expectedApproxTh.IsNull) + ITypeHandle? expectedApproxTh = ApproxTopLevel(dbi, rts, canonTh, expectedTh); + if (expectedApproxTh is null) return; // If the approximation rules collapse this type to null, skip the round-trip assertion. // Build the flat DebuggerIPCE_TypeArgData[] tree (preorder DFS) the right side would @@ -193,7 +193,7 @@ private static unsafe void FillTypeNodes(DacDbiImpl dbi, IRuntimeTypeSystem rts, // ApproxTypeArg. Array / Ptr / Byref preserve the outer shape; the inner type goes through // ApproxTypeArg. Anything else collapses to the primitive type for its element type // (e.g. System.Object, System.String, primitives). - private ITypeHandle ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) + private ITypeHandle? ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) { CorElementType et = GetElementType(rts, th); switch (et) @@ -201,16 +201,20 @@ private ITypeHandle ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, IType case CorElementType.Array: case CorElementType.SzArray: { - ITypeHandle elem = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); + ITypeHandle? elem = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); + if (elem is null) + return null; rts.IsArray(th, out uint rank); - return rts.GetConstructedType(elem, et, (int)rank, ImmutableArray.Empty); + return rts.GetConstructedType(elem, et, (int)rank, ImmutableArray.Empty); } case CorElementType.Ptr: case CorElementType.Byref: { - ITypeHandle referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); - return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + ITypeHandle? referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); + if (referent is null) + return null; + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } case CorElementType.Class: @@ -225,15 +229,17 @@ private ITypeHandle ApproxTopLevel(DacDbiImpl dbi, IRuntimeTypeSystem rts, IType // Arg context: Class collapses to __Canon (its children skipped); ValueType is recursively // approximated; Ptr preserves shape; obj-ref primitives (Class/Object/String/SzArray/Array) // collapse to __Canon; primitives map to their primitive ITypeHandle. - private ITypeHandle ApproxTypeArg(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) + private ITypeHandle? ApproxTypeArg(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) { CorElementType et = GetElementType(rts, th); switch (et) { case CorElementType.Ptr: { - ITypeHandle referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); - return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); + ITypeHandle? referent = ApproxTypeArg(dbi, rts, canonTh, rts.GetTypeParam(th)); + if (referent is null) + return null; + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } case CorElementType.Class: @@ -255,7 +261,7 @@ private ITypeHandle ApproxTypeArg(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeH // Non-generic types return early — the production walker takes the // nTypeArgs == 0 branch and returns the typeDef directly, which equals the type's // own MT for a non-generic type. - private ITypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) + private ITypeHandle? InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, ITypeHandle canonTh, ITypeHandle th) { // Mirror DacDbiImpl.FillClassTypeInfo: upcast continuation-without-metadata types to // their parent before resolving module / typeDef token. Otherwise the synthesized token @@ -280,16 +286,16 @@ private ITypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, ulong vmAssembly = loader.GetAssembly(moduleHandle).Value; uint metadataToken = rts.GetTypeDefToken(th); - ITypeHandle typeDef = dbi.TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); - if (typeDef.IsNull) - return ITypeHandle.Null; + ITypeHandle? typeDef = dbi.TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + if (typeDef is null) + return null; - ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(inst.Length); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(inst.Length); for (int i = 0; i < inst.Length; i++) { - ITypeHandle approxArg = ApproxTypeArg(dbi, rts, canonTh, inst[i]); - if (approxArg.IsNull) - return ITypeHandle.Null; + ITypeHandle? approxArg = ApproxTypeArg(dbi, rts, canonTh, inst[i]); + if (approxArg is null) + return null; builder.Add(approxArg); } @@ -298,9 +304,9 @@ private ITypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, // Same element-type mapping DacDbiImpl uses (System.String -> E_T_STRING, System.Object -> // E_T_OBJECT, else GetSignatureCorElementType). - private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle th) + private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle? th) { - if (th.IsNull) + if (th is null) return CorElementType.Void; if (rts.IsString(th)) return CorElementType.String; From 11ef2288661bfb7d128267a94ea43decef73c2e3 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 21 Jul 2026 00:03:55 -0400 Subject: [PATCH 22/23] Clarify ITypeHandle identity lifetime and nullable docs Document that canonical reference identity is scoped to a target cache epoch, fix nullable ITypeHandle grammar, and replace an implicit null-forgiving invariant with an actionable runtime guard. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- docs/design/datacontracts/RuntimeTypeSystem.md | 2 ++ docs/design/datacontracts/Signature.md | 2 +- .../TypeNameBuilder.cs | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index 7a76e071472190..41c516b234a566 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -13,6 +13,8 @@ Given a `TargetPointer` address, the `RuntimeTypeSystem` contract provides an `I // An opaque canonical identity for a runtime type. Handles are produced and // interned by RuntimeTypeSystem; consumers must not fabricate implementations. // A null reference represents the absence of a type. +// Canonical identity is scoped to a target cache epoch: after Target.Flush, +// resolving the same target address may return a different object reference. interface ITypeHandle { TargetPointer Address { get; } diff --git a/docs/design/datacontracts/Signature.md b/docs/design/datacontracts/Signature.md index 8265c52950da6a..6fbb7eb3c1c792 100644 --- a/docs/design/datacontracts/Signature.md +++ b/docs/design/datacontracts/Signature.md @@ -54,7 +54,7 @@ Constants: | `ELEMENT_TYPE_INTERNAL` | runtime-internal element type tag for an internal `TypeHandle` | `0x21` | | `ELEMENT_TYPE_CMOD_INTERNAL` | runtime-internal element type tag for an internal modified type | `0x22` | -Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer to a runtime `TypeHandle` (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to a `ITypeHandle`. +Decoding a signature follows the ECMA-335 §II.23.2 grammar. For all standard element types, decoding behaves identically to `System.Reflection.Metadata.SignatureDecoder`. When the decoder encounters one of the runtime-internal tags above, it reads the target-sized pointer to a runtime `TypeHandle` (and optional `required` byte for `ELEMENT_TYPE_CMOD_INTERNAL`) from the signature blob and resolves it to an `ITypeHandle`. The decoder is implemented as `RuntimeSignatureDecoder` -- a clone of SRM's `SignatureDecoder` with added support for the runtime-internal element types. The clone takes an additional `Target` so internal-type pointers can be sized for the target architecture. Provider implementations implement `IRuntimeSignatureTypeProvider` -- a superset of `System.Reflection.Metadata.ISignatureTypeProvider` -- adding methods for the runtime-internal element types: diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs index 8dcafeb9f7e585..5ec8a8a5f2b262 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs @@ -122,7 +122,8 @@ public static void AppendMethodImpl(Target target, StringBuilder stringBuilder, uint rowId = EcmaMetadataUtils.GetRowId(runtimeTypeSystem.GetMethodToken(method)); if (rowId != 0) { - Contracts.ModuleHandle module = loader.GetModuleHandleFromModulePtr(runtimeTypeSystem.GetModule(th!)); + ITypeHandle methodType = th ?? throw new InvalidOperationException("Metadata-backed method has no declaring type."); + Contracts.ModuleHandle module = loader.GetModuleHandleFromModulePtr(runtimeTypeSystem.GetModule(methodType)); MetadataReader reader = target.Contracts.EcmaMetadata.GetMetadata(module)!; MethodDefinition methodDef = reader.GetMethodDefinition(MetadataTokens.MethodDefinitionHandle((int)rowId)); stringBuilder.Append(reader.GetString(methodDef.Name)); From 4ea8f525c8ab095837be6023878774c1bde748a5 Mon Sep 17 00:00:00 2001 From: Max Charlamb Date: Tue, 21 Jul 2026 11:06:14 -0400 Subject: [PATCH 23/23] Align ManagedTypeSource docs with nullable outputs Update the authoritative pseudocode to use nullable ITypeHandle and MetadataReader outputs with NotNullWhen(true), matching the contract and implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3508d1b8-e4de-4d3e-981f-79fe92c12f2c --- docs/design/datacontracts/ManagedTypeSource.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/design/datacontracts/ManagedTypeSource.md b/docs/design/datacontracts/ManagedTypeSource.md index 465f48fd8e6621..3f492f0a744203 100644 --- a/docs/design/datacontracts/ManagedTypeSource.md +++ b/docs/design/datacontracts/ManagedTypeSource.md @@ -23,7 +23,7 @@ Target.TypeInfo GetTypeInfo(string fullyQualifiedName); // Return true and populate `typeHandle` with the ITypeHandle for the runtime type, // or false if the type cannot be resolved. -bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle? typeHandle); +bool TryGetTypeHandle(string fullyQualifiedName, [NotNullWhen(true)] out ITypeHandle? typeHandle); ITypeHandle GetTypeHandle(string fullyQualifiedName); // Return true and populate `address` with the address of the named static field, @@ -68,7 +68,11 @@ they read in their own `### Managed types used` section. ``` csharp // Type resolution: parse the fully-qualified name, walk System.Private.CoreLib's // metadata to locate the TypeDef, then map TypeDef -> MethodTable via the loader. -bool TryResolveType(string managedFqName, out ITypeHandle th, out MetadataReader mdReader, out TypeDefinition typeDef) +bool TryResolveType( + string managedFqName, + [NotNullWhen(true)] out ITypeHandle? th, + [NotNullWhen(true)] out MetadataReader? mdReader, + out TypeDefinition typeDef) { ILoader loader = target.Contracts.Loader; TargetPointer systemAssembly = loader.GetSystemAssembly(); @@ -96,14 +100,14 @@ bool TryResolveType(string managedFqName, out ITypeHandle th, out MetadataReader return true; } -bool TryGetTypeHandle(string fqn, out ITypeHandle? th) +bool TryGetTypeHandle(string fqn, [NotNullWhen(true)] out ITypeHandle? th) { return TryResolveType(fqn, out th, out _, out _); } bool TryGetTypeInfo(string fqn, out Target.TypeInfo info) { - if (!TryResolveType(fqn, out ITypeHandle th, out MetadataReader mdReader, out TypeDefinition typeDef)) + if (!TryResolveType(fqn, out ITypeHandle? th, out MetadataReader? mdReader, out TypeDefinition typeDef)) return false; IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem;