diff --git a/docs/design/datacontracts/ManagedTypeSource.md b/docs/design/datacontracts/ManagedTypeSource.md index 2e4b3a3ada9ae3..3f492f0a744203 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 ITypeHandle for the runtime type, // or false if the type cannot be resolved. -bool TryGetTypeHandle(string fullyQualifiedName, out TypeHandle typeHandle); -TypeHandle GetTypeHandle(string fullyQualifiedName); +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, // or false if the type / field cannot be resolved or its statics storage has not @@ -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 TypeHandle 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 TypeHandle th, out MetadataReader return true; } -bool TryGetTypeHandle(string fqn, out TypeHandle 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 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 +151,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 +178,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 +193,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..41c516b234a566 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 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 { - // no public constructors - - public TargetPointer Address { get; } - public bool IsNull => Address != 0; + TargetPointer Address { get; } } +// An internal 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,123 @@ 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`. +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`. ``` 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 ReadOnlySpan 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 ReadOnlySpan 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 +225,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 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); @@ -314,7 +321,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 +334,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 +486,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 +575,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,16 +610,16 @@ 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 ... // read Data.MethodTable from typeHandlePointer. ... // create a MethodTable_1 and add it to _methodTables. - return TypeHandle { Address = typeHandlePointer } + return GetOrCreateTargetTypeHandle(typeHandlePointer); } - public TargetPointer GetModule(TypeHandle TypeHandle) + public TargetPointer GetModule(ITypeHandle TypeHandle) { if (typeHandle.IsMethodTable()) { @@ -637,17 +644,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 +662,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 +693,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 +728,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 +759,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 +823,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 +836,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 +845,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 +867,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 +877,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 +894,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 +909,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 +922,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 +935,7 @@ Contracts used: return threadContract.GetThreadLocalStaticBase(threadPtr, tlsIndexAddr); } - public ReadOnlySpan GetInstantiation(TypeHandle TypeHandle) + public ReadOnlySpan GetInstantiation(ITypeHandle TypeHandle) { if (!typeHandle.IsMethodTable()) return default; @@ -942,14 +949,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 +966,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 +976,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 +986,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 +994,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 +1016,7 @@ Contracts used: return false; } - public CorElementType GetSignatureCorElementType(TypeHandle typeHandle) + public CorElementType GetSignatureCorElementType(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1040,7 +1047,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 +1059,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 +1068,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 +1077,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 +1087,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 +1111,7 @@ Contracts used: return false; } - public TypeHandle GetTypeParam(TypeHandle typeHandle) + public ITypeHandle GetTypeParam(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1135,9 +1142,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); + ReadOnlySpan instantiation = GetInstantiation(potentialMatch); if (instantiation.Length != typeArguments.Length) return false; @@ -1155,7 +1162,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 +1172,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 ReadOnlySpan candidateRetAndArgs, out SignatureCallingConvention candidateCallConv)) return false; if (candidateCallConv != callConv) return false; @@ -1181,7 +1188,7 @@ Contracts used: return true; } - private bool IsLoaded(TypeHandle typeHandle) + private bool IsLoaded(ITypeHandle typeHandle) { if (typeHandle.Address == TargetPointer.Null) return false; @@ -1196,15 +1203,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); + 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); - TypeHandle potentialMatch = new TypeHandle(TargetPointer.Null); + ITypeHandle? potentialMatch = null; foreach (TargetPointer ptr in loaderContract.GetAvailableTypeParams(moduleHandle)) { potentialMatch = GetTypeHandle(ptr); @@ -1227,10 +1234,10 @@ Contracts used: return potentialMatch; } } - return new TypeHandle(TargetPointer.Null); + return 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 +1245,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 +1267,7 @@ Contracts used: 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; @@ -1277,7 +1284,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 +1293,7 @@ Contracts used: return true; } - public bool IsPointer(TypeHandle typeHandle) + public bool IsPointer(ITypeHandle typeHandle) { if (!typeHandle.IsTypeDesc()) return false; @@ -1296,9 +1303,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 +1599,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 ReadOnlySpan GetGenericMethodInstantiation(MethodDescHandle methodDescHandle) { MethodDesc methodDesc = _methodDescs[methodDescHandle.Address]; @@ -1604,7 +1611,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 +1825,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 +2045,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 +2057,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 +2111,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 +2130,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 +2176,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 +2190,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 +2214,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 +2234,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,12 +2352,12 @@ 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 // 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). } @@ -2361,7 +2368,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 */; @@ -2384,7 +2391,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..6fbb7eb3c1c792 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 -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); @@ -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 (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 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: @@ -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 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 -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.Abstractions/CdacAttributes.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs index 96f9c4be01aaa7..cbbd3b9184f20e 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs @@ -32,8 +32,8 @@ public CdacTypeAttribute(params string[] names) /// /// When true, the generator emits a TypeHandle(Target) - /// accessor that resolves the runtime TypeHandle by trying each - /// candidate name against IManagedTypeSource. + /// 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/IManagedTypeSource.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs index 97154a6cbe0669..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,8 +17,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, [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(); 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..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 @@ -8,18 +8,13 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts; -// an opaque handle to a type handle. See IMetadata.GetMethodTableData -public readonly struct TypeHandle +/// +/// An opaque handle to a runtime type, backed by a target-process MethodTable or +/// TypeDesc address. +/// +public interface ITypeHandle { - // TODO-Layering: These members should be accessible only to contract implementations. - public TypeHandle(TargetPointer address) - { - Address = address; - } - - public TargetPointer Address { get; } - - public bool IsNull => Address == 0; + TargetPointer Address { get; } } public enum CorElementType @@ -143,121 +138,120 @@ 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 + #endregion ITypeHandle inspection APIs #region MethodDesc inspection APIs MethodDescHandle GetMethodDescHandle(TargetPointer targetPointer) => throw new NotImplementedException(); @@ -265,7 +259,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 +330,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..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); - 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/CallingConvention/ArgumentLocation.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CallingConvention/ArgumentLocation.cs index c00ac4284a9ec9..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 @@ -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..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 @@ -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 @@ -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) @@ -250,16 +252,15 @@ 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]; - 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,11 +288,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 +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)) @@ -333,7 +334,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 +415,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 +430,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 +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(TypeHandle 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); - 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 // (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 */ } @@ -539,15 +540,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 +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 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,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. - TypeHandle 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) @@ -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,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). - TypeHandle 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 542b461c2efeef..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 @@ -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; @@ -47,13 +48,13 @@ public CdacTypeHandle(TypeHandle typeHandle, Target target, CdacCorElementType k 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; @@ -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 @@ -72,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. @@ -88,11 +89,11 @@ 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 - // 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 @@ -107,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) @@ -124,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 @@ -174,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). @@ -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,10 +217,10 @@ 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); - 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/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/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..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; @@ -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(); } @@ -81,22 +85,26 @@ 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, [NotNullWhen(true)] out ITypeHandle? typeHandle) { - if (_typeHandleCache.TryGetValue(fullyQualifiedName, out typeHandle)) - return !typeHandle.IsNull; + if (_typeHandleCache.TryGetValue(fullyQualifiedName, out ITypeHandle? cached)) + { + typeHandle = cached; + return typeHandle is not null; + } if (!TryResolveType(fullyQualifiedName, out typeHandle, out _, out _)) { - _typeHandleCache[fullyQualifiedName] = new TypeHandle(TargetPointer.Null); + typeHandle = null; + _typeHandleCache[fullyQualifiedName] = null; return false; } @@ -128,7 +136,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 +171,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 +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 TypeHandle th, out _, out _)) + if (!TryResolveType(fullyQualifiedName, out ITypeHandle? th, out _, out _)) { fieldDescAddr = TargetPointer.Null; _fieldDescCache[key] = TargetPointer.Null; @@ -198,7 +206,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 +254,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, [NotNullWhen(true)] out ITypeHandle? th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef) { - th = new TypeHandle(TargetPointer.Null); + th = null; typeDef = default; ILoader loader = _target.Contracts.Loader; @@ -264,7 +272,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 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/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/TypeHandleImplementations.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs new file mode 100644 index 00000000000000..39a319171c8892 --- /dev/null +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Contracts; + +/// +/// A canonical ITypeHandle backed by a real target-process address +/// (MethodTable* or TypeDesc*). +/// +internal sealed class TargetTypeHandle : ITypeHandle +{ + internal TargetTypeHandle(TargetPointer address) + { + Address = address; + } + + public TargetPointer Address { get; } +} 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..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 @@ -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; @@ -31,13 +32,28 @@ 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(); + // 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 @@ -73,7 +89,7 @@ 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; ElementType = elementType; @@ -81,19 +97,19 @@ public TypeKey(TypeHandle typeHandle, CorElementType elementType, int rank, Immu TypeArgs = typeArgs; CallConv = callConv; } - public TypeHandle 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) { - 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; @@ -103,16 +119,17 @@ 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 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, th.GetHashCode()); + hash = HashCode.Combine(hash, th is null ? 0 : RuntimeHelpers.GetHashCode(th)); } return hash; } } - // 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 +370,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 +387,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 +481,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 +493,14 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) // if we already validated this address, return a handle if (_methodTables.ContainsKey(typeHandlePointer)) { - return new TypeHandle(typeHandlePointer); + return GetOrCreateTargetTypeHandle(typeHandlePointer); } // Check for a TypeDesc if (addressLowBits == TypeHandleBits.TypeDesc) { // This is a TypeDesc - return new TypeHandle(typeHandlePointer); + return GetOrCreateTargetTypeHandle(typeHandlePointer); } TargetPointer methodTablePointer = typeHandlePointer; @@ -494,7 +511,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 GetOrCreateTargetTypeHandle(methodTablePointer); } // If it's the free object method table, we trust it to be valid @@ -503,10 +520,10 @@ 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 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)); @@ -515,9 +532,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 GetOrCreateTargetTypeHandle(methodTablePointer); } - public TargetPointer GetModule(TypeHandle typeHandle) + public TargetPointer GetModule(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -544,17 +561,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 +582,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 +590,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 +622,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 +662,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 +671,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 +690,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); @@ -705,9 +722,10 @@ public bool TryGetHFAElementSize(TypeHandle 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; @@ -719,7 +737,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 +791,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 +812,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 +893,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 +911,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; @@ -912,7 +930,7 @@ public IEnumerable GetFieldDescList(TypeHandle 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; @@ -921,14 +939,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 +959,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 +968,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 +977,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 +986,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 +995,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 +1004,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 +1016,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 +1025,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 +1038,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 +1054,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 +1062,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 +1078,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 +1091,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 +1114,7 @@ public bool HasTypeParam(TypeHandle typeHandle) return false; } - public CorElementType GetSignatureCorElementType(TypeHandle typeHandle) + public CorElementType GetSignatureCorElementType(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1127,7 +1145,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 +1158,7 @@ public CorElementType GetInternalCorElementType(TypeHandle typeHandle) return sigType; } - public bool IsValueType(TypeHandle typeHandle) + public bool IsValueType(ITypeHandle typeHandle) { if (typeHandle.IsMethodTable()) { @@ -1156,7 +1174,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 +1186,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 +1195,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 +1221,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 +1247,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 +1257,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; @@ -1253,13 +1271,13 @@ private bool GenericInstantiationMatch(TypeHandle genericType, TypeHandle potent 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; } - 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 +1287,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; @@ -1279,13 +1297,13 @@ private bool FnPtrMatch(TypeHandle candidate, ImmutableArray retAndA 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; } - private bool IsLoaded(TypeHandle typeHandle) + private bool IsLoaded(ITypeHandle typeHandle) { if (typeHandle.Address == TargetPointer.Null) return false; @@ -1300,29 +1318,34 @@ 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)) + 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; TargetPointer loaderModule; 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); - TypeHandle potentialMatch; + ITypeHandle potentialMatch; foreach (TargetPointer ptr in loaderContract.GetAvailableTypeParams(moduleHandle)) { 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; @@ -1336,17 +1359,17 @@ TypeHandle IRuntimeTypeSystem.GetConstructedType(TypeHandle typeHandle, CorEleme 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 new TypeHandle(TargetPointer.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; @@ -1361,8 +1384,9 @@ private TargetPointer ComputeLoaderModule(TargetPointer definitionModule, Immuta } bool anyCollectible = false; - foreach (TypeHandle arg in inst) + foreach (ITypeHandle? nullableArg in inst) { + ITypeHandle arg = nullableArg!; if (arg.Address == TargetPointer.Null) continue; @@ -1416,7 +1440,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 +1448,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 +1470,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 +1489,7 @@ public bool IsFunctionPointer(TypeHandle typeHandle, out ReadOnlySpan typeHandle.IsTypeDesc(); + public bool IsTypeDesc(ITypeHandle typeHandle) => typeHandle.IsTypeDesc(); public TypedByRefInfo GetTypedByRefInfo(TargetPointer typedByRef) { @@ -1483,7 +1507,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 +1537,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 +1546,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 +1618,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 +1901,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 +1962,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 +2021,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 +2047,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 +2061,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 +2086,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 +2094,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 +2107,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 +2143,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 +2205,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 +2299,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 +2307,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,22 +2363,22 @@ 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); + return null; + ITypeHandle enclosingType = GetTypeHandle(enclosingMT); TargetPointer modulePtr = GetModule(enclosingType); if (modulePtr == TargetPointer.Null) - return default; + return null; ModuleHandle moduleHandle = _target.Contracts.Loader.GetModuleHandleFromModulePtr(modulePtr); MetadataReader? mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle); if (mdReader is null) - return default; + return null; uint memberDef = ((IRuntimeTypeSystem)this).GetFieldDescMemberDef(fieldDescPointer); FieldDefinitionHandle fieldDefHandle = (FieldDefinitionHandle)MetadataTokens.Handle((int)memberDef); @@ -2364,7 +2388,7 @@ TypeHandle IRuntimeTypeSystem.GetFieldDescApproxTypeHandle(TargetPointer fieldDe } catch { - return default; + return null; } } @@ -2386,7 +2410,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 +2468,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..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 TypeHandle 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 TypeHandle 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); } 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..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 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,56 @@ 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)) + if (typeof(T) == typeof(ITypeHandle)) { - typeContext = (TypeHandle)(object)context!; + ITypeHandle? typeContext = (ITypeHandle?)(object?)context; + if (typeContext is null) + return null; 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 ? 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 ? 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) + ? 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..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; } - 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/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 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..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 @@ -7,20 +7,20 @@ 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; + return type.Address != TargetPointer.Null && ((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; + return type.Address != TargetPointer.Null && ((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; + return TargetPointer.Null; return (ulong)type.Address & ~(ulong)RuntimeTypeSystem_1.TypeHandleBits.ValidMask; } 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..6fec9c49a25312 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs @@ -45,9 +45,9 @@ 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; + 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/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) { 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); @@ -2626,7 +2620,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 +2720,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 +2749,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,11 +2873,11 @@ 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(); - 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; - TypeHandle th = default; + 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; } @@ -2958,10 +2952,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 +2981,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,52 +2992,56 @@ 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) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } - 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) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } - 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()); + return rts.GetConstructedType(typeConstructor, CorElementType.GenericInst, 0, builder.MoveToImmutable()) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } - 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])); // 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(null, CorElementType.FnPtr, 0, builder.MoveToImmutable()) + ?? throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; } public int EnumerateMethodDescParams(ulong vmMethodDesc, ulong genericsToken, uint* pcGenericClassTypeParams, @@ -3066,13 +3064,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,9 +3099,9 @@ 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); - if (!thMatch.IsNull) + ITypeHandle thFromThis = rts.GetTypeHandle(new TargetPointer(genericsToken)); + ITypeHandle? thMatch = GetMethodTableMatchingParentClass(rts, thFromThis, thRepMt); + if (thMatch is not null) { thSpecificClass = thMatch; isExact = true; @@ -3125,19 +3123,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 is null + ? default : 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 +3351,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); - if (th.IsNull) + ITypeHandle? th = TryLookupTypeDefOrRefInAssembly(vmAssembly, metadataToken); + if (th is null) 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; @@ -3377,10 +3375,10 @@ internal TypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metad mt = loader.GetModuleLookupMapElement(lookupTables.TypeRefToMethodTable, metadataToken, out _); break; default: - return default; + return null; } if (mt == TargetPointer.Null) - return default; + return null; return rts.GetTypeHandle(mt); } @@ -3397,8 +3395,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,12 +3472,7 @@ public int GetSimpleType(int simpleType, uint* pMetadataToken, ulong* pVmModule) try { Contracts.IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = rts.GetPrimitiveType((CorElementType)simpleType); - - if (typeHandle.IsNull) - { - throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_CLASS_NOT_LOADED)!; - } + ITypeHandle typeHandle = rts.GetPrimitiveType((CorElementType)simpleType); Debug.Assert(pMetadataToken != null); *pMetadataToken = rts.GetTypeDefToken(typeHandle); @@ -3530,7 +3523,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 +3709,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.TypeHandle); FillBasicTypeInfo(rts, th, out DebuggerIPCE_BasicTypeData typeData); *pTypedByRefType = typeData; *pObjRef = info.Data.Value; @@ -3754,7 +3747,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 +3786,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 +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 - TypeHandle th = default; + 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; @@ -4716,7 +4709,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 +4721,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 +4762,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,11 +4774,11 @@ 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); - if (fieldTypeHandle.IsNull) + ITypeHandle? fieldTypeHandle = signature.DecodeFieldSignature(fieldDef.Signature, enclosingModuleHandle, enclosingTypeHandle); + if (fieldTypeHandle is null) { corField->id = default; corField->fieldType = 0; @@ -4802,7 +4795,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 +4806,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 +4860,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 +4869,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 +4916,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 +4937,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 +5398,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 +5463,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 +5748,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 +5762,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,11 +5776,11 @@ 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++) + for (int i = 0; i < 1000; i++) { if (HasSameTypeDefAs(rts, current, parent)) return current; @@ -5797,11 +5790,11 @@ private static TypeHandle GetMethodTableMatchingParentClass(IRuntimeTypeSystem r prev = current.Address; current = rts.GetTypeHandle(next); } - return default; + return null; } // 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,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, TypeHandle typeHandle) + private static CorElementType GetElementType(IRuntimeTypeSystem rts, ITypeHandle? typeHandle) { - if (typeHandle.IsNull) + if (typeHandle is null) return CorElementType.Void; if (rts.IsString(typeHandle)) @@ -5864,7 +5857,7 @@ private static CorElementType GetElementType(IRuntimeTypeSystem rts, TypeHandle // Mirrors native TypeHandle::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 +5870,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 +5888,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 +5902,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 +5917,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 +5931,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 an ITypeHandle through GetExactTypeHandle. + internal void FillBasicTypeInfo(IRuntimeTypeSystem rts, ITypeHandle typeHandle, out DebuggerIPCE_BasicTypeData typeInfo) { typeInfo = default; CorElementType elementType = GetElementType(rts, typeHandle); @@ -5965,7 +5958,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/TypeDataWalk.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs index 706073acec0a2c..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 @@ -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 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). // @@ -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 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 null; CorElementType et = (CorElementType)DacDbiImpl.ReadLittleEndian(p->data.elementType); switch (et) @@ -114,61 +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); - if (typeDef.IsNull) - return default; + 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++) { - TypeHandle th = ReadLoadedTypeArg(); - allOK &= !th.IsNull; + ITypeHandle? th = ReadLoadedTypeArg(); + if (th is null) + return null; builder.Add(th); } - if (!allOK) - return default; return _rts.GetConstructedType(typeDef, CorElementType.GenericInst, 0, builder.MoveToImmutable()); } - private TypeHandle ArrayTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle? ArrayTypeArg(DebuggerIPCE_TypeArgData* pInfo) { - TypeHandle elem = ReadLoadedTypeArg(); - if (elem.IsNull) - return default; + 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 TypeHandle PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData* pInfo) + private ITypeHandle? PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData* pInfo) { - TypeHandle referent = ReadLoadedTypeArg(); - if (referent.IsNull) - return default; + 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 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) + if ((typeDef is not null && _rts.IsValueType(typeDef)) || et == CorElementType.ValueType) { return ReadLoadedInstantiation(vmAssembly, metadataToken, numTypeArgs); } @@ -180,25 +178,23 @@ 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); - bool allOK = true; + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder((int)numTypeArgs); for (uint i = 0; i < numTypeArgs; i++) { - TypeHandle th = ReadLoadedTypeArg(); - allOK &= !th.IsNull; + ITypeHandle? th = ReadLoadedTypeArg(); + if (th is null) + return null; builder.Add(th); } - if (!allOK) - return default; // Non-default calling conventions are not supported (matches the exact-handle path). - return _rts.GetConstructedType(default, CorElementType.FnPtr, 0, builder.MoveToImmutable()); + return _rts.GetConstructedType(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 +206,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 +222,10 @@ private TypeHandle TryLookupTypeDefOrRefInAssembly(ulong vmAssembly, uint metada mt = loader.GetModuleLookupMapElement(lookupTables.TypeRefToMethodTable, metadataToken, out _); break; default: - return default; + return null; } if (mt == TargetPointer.Null) - return default; + return 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 85bd1ad8f10c26..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); @@ -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 (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,8 +425,8 @@ private bool HasClassInstantiation(MethodDescHandle md) IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; TargetPointer mtAddr = rts.GetMethodTable(md); - TypeHandle mt = rts.GetTypeHandle(mtAddr); - return !rts.GetInstantiation(mt).IsEmpty; + ITypeHandle mt = rts.GetTypeHandle(mtAddr); + 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/SOSDacImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs index 6d03e9990c2440..ef620a6554aae8 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs @@ -1067,21 +1067,21 @@ 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 (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)) @@ -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)); + 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)); + 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)); + 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); + 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)); + 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)); + 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)); + 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); + 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)); + 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..0838d6e542991a 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs @@ -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,12 +308,15 @@ 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; - if (typeHandle.IsNull) + if (typeHandle is null) + { stringBuilder.Append("**UNKNOWN TYPE**"); + return; + } CorElementType corElementType = runtimeTypeSystem.GetSignatureCorElementType(typeHandle); if (corElementType == CorElementType.ValueType && runtimeTypeSystem.HasTypeParam(typeHandle)) { @@ -358,7 +361,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 +417,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..5ec8a8a5f2b262 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 = null; bool isNoMetadataMethod = runtimeTypeSystem.IsNoMetadataMethod(method, out methodName); if (isNoMetadataMethod) @@ -122,14 +122,15 @@ 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)); } } - ReadOnlySpan genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); + ReadOnlySpan genericMethodInstantiation = runtimeTypeSystem.GetGenericMethodInstantiation(method); if (genericMethodInstantiation.Length > 0 && !runtimeTypeSystem.IsGenericMethodDefinition(method)) { AppendInst(target, stringBuilder, genericMethodInstantiation, format); @@ -142,11 +143,11 @@ 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; - if (!th.IsNull) + ReadOnlySpan typeInstantiationSigFormat = default; + if (th is not null) { 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 @@ -158,9 +159,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,22 +185,22 @@ 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, 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, 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, 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)"); } @@ -212,13 +213,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, (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), default, 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.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 +300,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 +330,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 +507,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..25a85d5ed91f9b 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} TypeHandle({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..1806023ac820a1 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..c2db5df9492bd1 100644 --- a/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs @@ -94,10 +94,8 @@ 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); - Assert.False(typeHandle.IsNull, - $"Expected non-null TypeHandle for MethodTable 0x{iface.MethodTable:X} in CCW 0x{ccwPtr:X}"); + // Verify the MethodTable is readable by resolving it to an ITypeHandle. + ITypeHandle typeHandle = rts.GetTypeHandle(iface.MethodTable); 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 aaec6b81b595a2..851f255f78bcf3 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 = 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)) @@ -51,27 +51,28 @@ 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. 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, [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 2c9d3c570f4d68..a2aa905e690af4 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,15 +81,15 @@ 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); - 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 @@ -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); + 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++) @@ -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,20 @@ 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)); + 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: { - 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)); + if (referent is null) + return null; + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } case CorElementType.Class: @@ -224,16 +228,18 @@ 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)); + if (referent is null) + return null; + return rts.GetConstructedType(referent, et, 0, ImmutableArray.Empty); } case CorElementType.Class: @@ -255,7 +261,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 +274,7 @@ private TypeHandle InstantiationApprox(DacDbiImpl dbi, IRuntimeTypeSystem rts, T th = rts.GetTypeHandle(parentMT); } - ReadOnlySpan inst = rts.GetInstantiation(th); + ReadOnlySpan inst = rts.GetInstantiation(th); if (inst.Length == 0) return th; @@ -280,16 +286,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); - if (typeDef.IsNull) - return default; + 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++) { - TypeHandle approxArg = ApproxTypeArg(dbi, rts, canonTh, inst[i]); - if (approxArg.IsNull) - return default; + ITypeHandle? approxArg = ApproxTypeArg(dbi, rts, canonTh, inst[i]); + if (approxArg is null) + return null; builder.Add(approxArg); } @@ -298,9 +304,9 @@ 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) + if (th is null) return CorElementType.Void; if (rts.IsString(th)) return CorElementType.String; 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..5ebce7f22bc981 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))); @@ -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) @@ -264,7 +281,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 +308,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 +328,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 +350,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 +373,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 +393,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/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 0758ea776d196a..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) { - TypeHandle handle = new TypeHandle(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 1f91dd724dc280..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 TypeHandle(objectMT)); - mockRts.Setup(r => r.GetParentMethodTable(new TypeHandle(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 TypeHandle(current)); - mockRts.Setup(r => r.GetParentMethodTable(new TypeHandle(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/ExceptionTests.cs b/src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs index 3f4e527eb91fee..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", }); - TypeHandle 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 { - TypeHandle 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 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..ec2c5ea08375a2 100644 --- a/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs +++ b/src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs @@ -83,12 +83,28 @@ public void HasRuntimeTypeSystemContract(MockTarget.Architecture arch) builder => freeObjectMethodTableAddress = builder.FreeObjectMethodTableAddress); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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)); } + [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) @@ -99,7 +115,7 @@ public void ValidateSystemObjectMethodTable(MockTarget.Architecture arch) rtsBuilder => systemObjectMethodTablePtr = rtsBuilder.SystemObjectMethodTable.Address); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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)); @@ -139,7 +155,7 @@ public void ValidateSystemStringMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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)); @@ -249,7 +265,7 @@ public void ValidateGenericInstMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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)); @@ -305,7 +321,7 @@ public void ValidateArrayInstMethodTable(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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)); @@ -368,7 +384,7 @@ public void IsContinuationWithoutMetadata_ReturnsTrueForContinuationType(MockTar }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.True(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); Assert.False(contract.IsFreeObjectMethodTable(continuationTypeHandle)); Assert.False(contract.IsString(continuationTypeHandle)); @@ -467,11 +483,11 @@ public void ValidateMultidimArrayRank(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle rank4Handle = contract.GetTypeHandle(rank4MethodTablePtr); + ITypeHandle rank4Handle = contract.GetTypeHandle(rank4MethodTablePtr); Assert.True(contract.IsArray(rank4Handle, out uint rank4)); Assert.Equal(4u, rank4); - Contracts.TypeHandle rank1Handle = contract.GetTypeHandle(rank1MultiDimMethodTablePtr); + ITypeHandle rank1Handle = contract.GetTypeHandle(rank1MultiDimMethodTablePtr); Assert.True(contract.IsArray(rank1Handle, out uint rank1)); Assert.Equal(1u, rank1); } @@ -501,10 +517,10 @@ public void IsContinuationWithoutMetadata_ReturnsFalseWhenGlobalIsNull(MockTarge }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); + ITypeHandle objectTypeHandle = contract.GetTypeHandle(systemObjectMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(objectTypeHandle)); - Contracts.TypeHandle childTypeHandle = contract.GetTypeHandle(childMethodTablePtr); + ITypeHandle childTypeHandle = contract.GetTypeHandle(childMethodTablePtr); Assert.False(contract.IsContinuationWithoutMetadata(childTypeHandle)); } @@ -538,7 +554,7 @@ public void ValidateContinuationMethodTablePointer(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); + ITypeHandle continuationTypeHandle = contract.GetTypeHandle(continuationInstanceMethodTablePtr); Assert.Equal(continuationInstanceMethodTablePtr.Value, continuationTypeHandle.Address.Value); Assert.True(contract.IsContinuationWithoutMetadata(continuationTypeHandle)); } @@ -566,7 +582,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 +610,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 +624,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 +663,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 +862,7 @@ public void RequiresAlign8(MockTarget.Architecture arch, bool flagSet) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(methodTablePtr); + ITypeHandle typeHandle = contract.GetTypeHandle(methodTablePtr); Assert.Equal(flagSet, contract.RequiresAlign8(typeHandle)); } @@ -865,7 +881,7 @@ public void GetGCDescSeriesReturnsEmptyForNonMethodTable(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeDescHandle = contract.GetTypeHandle(typeDescAddress); + ITypeHandle typeDescHandle = contract.GetTypeHandle(typeDescAddress); Assert.Empty(contract.GetGCDescSeries(typeDescHandle)); } @@ -891,7 +907,7 @@ public void GetGCDescSeriesReturnsEmptyWhenNoGCPointers(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.False(contract.ContainsGCPointers(typeHandle)); Assert.Empty(contract.GetGCDescSeries(typeHandle)); } @@ -938,7 +954,7 @@ public void GetGCDescSeriesReturnsSingleSeries(MockTarget.Architecture arch) }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle).ToArray(); @@ -993,7 +1009,7 @@ public void GetGCDescSeriesReturnsMultipleSeriesInOrder(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); (uint Offset, uint Size)[] series = contract.GetGCDescSeries(typeHandle).ToArray(); Assert.Equal(expectedSeries.Length, series.Length); @@ -1049,7 +1065,7 @@ public void GetGCDescSeriesReturnsSingleValueClassSeries(MockTarget.Architecture }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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. @@ -1108,7 +1124,7 @@ public void GetGCDescSeriesReturnsMultipleValueClassSeries(MockTarget.Architectu }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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(); @@ -1169,7 +1185,7 @@ public void GetGCDescSeriesRegularSeriesWithArrayNumComponents(MockTarget.Archit }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle typeHandle = contract.GetTypeHandle(mtPtr); + ITypeHandle typeHandle = contract.GetTypeHandle(mtPtr); Assert.True(contract.ContainsGCPointers(typeHandle)); uint pointerSz = (uint)target.PointerSize; @@ -1227,7 +1243,7 @@ public void GetGCDescSeriesValueClassRepeatingWithArrayNumComponents(MockTarget. }); IRuntimeTypeSystem contract = target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle 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; diff --git a/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs b/src/native/managed/cdac/tests/UnitTests/ObjectTests.cs index aec9e6e73763d1..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(); - TypeHandle handle = new TypeHandle(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(); - TypeHandle handle = new TypeHandle(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 5134255237294d..9058be1b6d3b9c 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 TargetTypeHandle(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..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); - TypeHandle typeHandle = new TypeHandle(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 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); }