[cdac] Extract ITypeHandle interface and add synthetic type handles#129800
[cdac] Extract ITypeHandle interface and add synthetic type handles#129800max-charlamb wants to merge 3 commits into
Conversation
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
There was a problem hiding this comment.
Pull request overview
This PR refactors cDAC’s type identity from a concrete TypeHandle struct to an ITypeHandle abstraction, enabling “synthetic” (reader-fabricated) handles for unloaded constructed types (Ptr/Byref/SZArray/Array) and updating the contracts/legacy layers/tests accordingly.
Changes:
- Introduces
ITypeHandle(+ null/synthetic/target-backed implementations) and updates contracts to traffic inITypeHandle. - Updates
RuntimeTypeSystem_1.GetConstructedTypeto synthesize constructed types on miss for Ptr/Byref/SZArray/Array. - Updates legacy SOS/DacDbi code and cDAC unit/dump tests to consume the new handle abstraction.
Reviewed changes
Copilot reviewed 52 out of 52 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/native/managed/cdac/tests/UnitTests/TypeDescTests.cs | Updates unit tests to use ITypeHandle and array-returning APIs. |
| src/native/managed/cdac/tests/UnitTests/SOSDacInterface5Tests.cs | Switches test setup to TargetTypeHandle. |
| src/native/managed/cdac/tests/UnitTests/RuntimeMutableTypeSystemTests.cs | Updates Moq setups and APIs to ITypeHandle. |
| src/native/managed/cdac/tests/UnitTests/ObjectTests.cs | Updates object contract tests to use TargetTypeHandle. |
| src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs | Replaces TypeHandle usage with ITypeHandle across MT tests. |
| src/native/managed/cdac/tests/UnitTests/MethodDescTests.cs | Updates generic-instantiation test assertions to use ITypeHandle[]. |
| src/native/managed/cdac/tests/UnitTests/ExceptionTests.cs | Updates exception contract tests to use TargetTypeHandle. |
| src/native/managed/cdac/tests/UnitTests/DacDbiImplTests.cs | Updates DacDbi tests to use TargetTypeHandle and new APIs. |
| src/native/managed/cdac/tests/UnitTests/CodeVersionsTests.cs | Updates code versions test helpers to use ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs | Updates dump tests to the ITypeHandle API surface. |
| src/native/managed/cdac/tests/DumpTests/ObjectiveCMarshalDumpTests.cs | Updates dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/IXCLRDataValueDumpTests.cs | Updates commentary/type references for ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/IXCLRDataMethodDefinitionDumpTests.cs | Updates dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs | Updates DacDbi dump tests and helpers to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs | Updates DacDbi loader dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiExactTypeHandleDumpTests.cs | Updates exact-typehandle roundtrip dump test to ITypeHandle. |
| src/native/managed/cdac/tests/DumpTests/CCWDumpTests.cs | Updates CCW dump test wording and ITypeHandle usage. |
| src/native/managed/cdac/tests/DumpTests/AsyncContinuationDumpTests.cs | Updates continuation dump tests to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/TypeNameBuilder.cs | Updates type/method name formatting to consume ITypeHandle and array-returning instantiation APIs. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs | Updates IXCLRDataProcess implementation to ITypeHandle and array-returning APIs. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs | Updates SOS DAC implementation to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SigFormat.cs | Updates signature formatting helpers to use ITypeHandle and array-returning APIs. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs | Updates interop struct comments to refer to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/Helpers/HeapWalk.cs | Updates heap-walk helper to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs | Updates DacDbi implementation to use ITypeHandle and constructed-type synthesis. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs | Updates method instance implementation to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs | Updates generic-instantiation checks to ITypeHandle[]. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs | Updates frame/type resolution paths to use ITypeHandle and array-returning instantiations. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/ExtensionMethods.cs | Adapts type-handle helper extensions to operate on ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs | Updates GC signature decoding context and lookups to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameHelpers.cs | Updates frame helper logic to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/SignatureTypeProvider.cs | Updates signature type provider to produce/consume ITypeHandle and constructed types. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/Signature_1.cs | Updates signature contract implementation to decode to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/IRuntimeSignatureTypeProvider.cs | Updates documentation for “internal type” handling to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem/TypeHandleImplementations.cs | Adds TargetTypeHandle and SyntheticTypeHandle implementations of ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs | Core RuntimeTypeSystem changes: ITypeHandle plumbing + synthetic constructed-type behavior. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeMutableTypeSystem_1.cs | Updates mutable type system APIs to accept ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Object_1.cs | Updates object sizing/array logic to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ManagedTypeSource_1.cs | Updates managed type resolution/caching to ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs | Updates exception-clause reading path to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Exception_1.cs | Updates exception contract implementation to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ConditionalWeakTable_1.cs | Updates CWT contract implementation to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ComWrappers_1.cs | Updates RCW detection to use the renamed generated type-handle accessor. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/CodeVersions_1.cs | Updates code-versions contract to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignature.cs | Changes signature decoding contract to return ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs | Introduces ITypeHandle/NullTypeHandle and updates the RuntimeTypeSystem contract signatures. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeMutableTypeSystem.cs | Updates mutable-type-system contract signature to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IManagedTypeSource.cs | Updates managed type source contract to use ITypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs | Updates generator-related docs to refer to ITypeHandle. |
| src/native/managed/cdac/gen/TypeNameResolverSource.cs | Updates generated helper to return ITypeHandle. |
| src/native/managed/cdac/gen/Emitter.cs | Updates generated output to reference ITypeHandle. |
| src/native/managed/cdac/gen/CdacGenerator.cs | Updates generator docs to refer to ITypeHandle. |
| /// <summary> | ||
| /// An opaque handle to a runtime type. May represent a loaded type (backed by a | ||
| /// target-process MethodTable or TypeDesc address) or a synthetic type fabricated | ||
| /// by the reader for unloaded constructed types. | ||
| /// </summary> | ||
| public interface ITypeHandle : IEquatable<ITypeHandle> | ||
| { | ||
| // TODO-Layering: These members should be accessible only to contract implementations. | ||
| public TypeHandle(TargetPointer address) | ||
| { | ||
| Address = address; | ||
| } | ||
|
|
||
| public TargetPointer Address { get; } | ||
| TargetPointer Address { get; } | ||
| bool IsNull { get; } | ||
| bool IsSynthetic { get; } | ||
| static ITypeHandle Null { get; } = NullTypeHandle.Instance; | ||
| } |
| public bool IsNull => Address == 0; | ||
| public bool IsSynthetic => false; | ||
|
|
||
| public bool Equals(ITypeHandle? other) | ||
| => other is TargetTypeHandle t && Address == t.Address; | ||
| public bool Equals(TargetTypeHandle other) => Address == other.Address; |
| @@ -474,14 +474,14 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) | |||
| // if we already validated this address, return a handle | |||
| if (_methodTables.ContainsKey(typeHandlePointer)) | |||
| { | |||
| return new TypeHandle(typeHandlePointer); | |||
| return new TargetTypeHandle(typeHandlePointer); | |||
| // No loaded match found. For Ptr/Byref/SzArray/Array, synthesize a handle | ||
| // so signature-decoding contracts can treat unloaded constructed types uniformly. | ||
| if (corElementType is CorElementType.Ptr or CorElementType.Byref or CorElementType.SzArray or CorElementType.Array) | ||
| { | ||
| var synthetic = new SyntheticTypeHandle(corElementType, typeHandle, rank); | ||
| _ = _typeHandles.TryAdd(new TypeKey(typeHandle, corElementType, rank, typeArguments), synthetic); | ||
| return synthetic; | ||
| } |
Rename the TypeHandle struct to ITypeHandle across the entire cDAC codebase in preparation for converting it to an interface that supports synthetic type handles for unloaded constructed types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…peHandle Convert ITypeHandle from a readonly struct to an interface, enabling polymorphic type handles. Add NullTypeHandle (Abstractions) and TargetTypeHandle (Contracts) implementations. Replace ReadOnlySpan with ITypeHandle[] in public API signatures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1c85305 to
2050b89
Compare
Am I missing something, or where are you removing said side channels with this abstraction? If this is a helper for a PR that you have in progress, what does it look like before and after? |
I needed extra data for implementing the ArgIterator: https://github.com/dotnet/runtime/pull/129769/changes#r3468318817 I believe adding synthetic typehandles aligns with our long-term goal to not have to load things in the runtime just for diagnostics. |
Could we accomplish this by adding (optional) fields and properties to the TypeHandle struct? |
The |
2050b89 to
6522cf8
Compare
| public sealed class NullTypeHandle : ITypeHandle | ||
| { | ||
| public static readonly NullTypeHandle Instance = new(); | ||
| private NullTypeHandle() { } |
| public bool Equals(ITypeHandle? other) | ||
| => other is TargetTypeHandle t && Address == t.Address; | ||
| public bool Equals(TargetTypeHandle other) => Address == other.Address; |
| if (corElementType is CorElementType.Ptr or CorElementType.Byref or CorElementType.SzArray or CorElementType.Array) | ||
| { | ||
| var synthetic = new SyntheticTypeHandle(corElementType, typeHandle, rank); | ||
| _ = _typeHandles.TryAdd(new TypeKey(typeHandle, corElementType, rank, typeArguments), synthetic); | ||
| return synthetic; |
| foreach (ITypeHandle arg in retAndArgTypes) | ||
| { | ||
| if (arg.Address == TargetPointer.Null) | ||
| continue; |
| // 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. | ||
| // DAC equivalent: src/coreclr/vm/typehandle.inl TypeHandle::GetMethodTable | ||
| // In the future we may want to return a ITypeHandle instead of a MethodTable, and modify SOS to do more complete pretty-printing. | ||
| // DAC equivalent: src/coreclr/vm/typehandle.inl ITypeHandle::GetMethodTable | ||
| if (rtsContract.IsFunctionPointer(foundTypeHandle, out _, out _) || rtsContract.IsPointer(foundTypeHandle)) |
| // Shared core implementation for TypeHandleToExpandedTypeInfo and GetObjectExpandedTypeInfo. | ||
| private void TypeHandleToExpandedTypeInfoImpl(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, TypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) | ||
| private void ITypeHandleToExpandedTypeInfoImpl(IRuntimeTypeSystem rts, AreValueTypesBoxed boxed, ITypeHandle typeHandle, DebuggerIPCE_ExpandedTypeData* pTypeInfo) | ||
| { |
Add SyntheticTypeHandle (internal) for Ptr, Byref, SzArray, and Array types that the runtime has not loaded. GetConstructedType now returns a synthetic handle on miss instead of null, enabling signature-decoding contracts to treat all parameter types uniformly. Synthetic-aware branches added to 10 RTS methods: - GetSignatureCorElementType, HasTypeParam, GetTypeParam - IsPointer, IsArray, ContainsGenericVariables - GetModule, GetLoaderModule, IsLoaded - GetConstructedType (synthesis on miss) Also fixes GcSignatureTypeProvider to use IsNull instead of Address comparison, so synthetics get properly classified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
6522cf8 to
791163a
Compare
Ok, sounds good |
Summary
Convert
TypeHandlefrom a readonly struct to theITypeHandleinterface, enabling synthetic (reader-fabricated) TypeHandles for unloaded constructed types (Ptr, Byref, SzArray, Array).Changes
TypeHandle->ITypeHandleacross entire cDAC codebaseITypeHandleinterface in Abstractions withAddress,IsNull,IsSyntheticNullTypeHandlesingleton in Abstractions (ITypeHandle.Null)TargetTypeHandlestruct in Contracts (real target-backed handles)SyntheticTypeHandleinternal class in Contracts (unloaded constructed types)GetConstructedTypesynthesizes on miss for Ptr/Byref/SzArray/Array instead of returning nullReadOnlySpan<TypeHandle>replaced withITypeHandle[]in public APIMotivation
When decoding method signatures, the runtime frequently has no loaded TypeHandle for constructed types like
int*,ref T, orT[]. PreviouslyGetConstructedTypereturned null, forcing consumers into ad-hoc side-channels. Now it returns a synthetic handle that downstream contracts can query uniformly.Note
This content was generated with the assistance of GitHub Copilot.