Skip to content

Commit 6083571

Browse files
Max CharlambCopilot
andcommitted
WIP: RuntimeSignatureDecoder, centralized SignatureDecoder contract
- Move RuntimeSignatureDecoder to Contracts/Signature/ - Move GcSignatureTypeProvider to Contracts/Signature/ with module-scoped caching - Add DecodeMethodSignatureForGC(BlobHandle, ModuleHandle) to ISignatureDecoder - Add DecodeFieldSignature to RuntimeSignatureDecoder - Add BlobHandleSignatureReader for lazy blob reading - SignatureTypeProvider implements IRuntimeSignatureTypeProvider - Switch DecodeFieldSignature to use RuntimeSignatureDecoder - GcScanner uses contract API instead of direct decoder construction Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 6e51115 commit 6083571

7 files changed

Lines changed: 609 additions & 79 deletions

File tree

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ISignatureDecoder.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,33 @@
66

77
namespace Microsoft.Diagnostics.DataContractReader.Contracts;
88

9+
/// <summary>
10+
/// Classification of a signature type for GC scanning purposes.
11+
/// </summary>
12+
public enum GcTypeKind
13+
{
14+
/// <summary>Not a GC reference (primitives, pointers).</summary>
15+
None,
16+
/// <summary>Object reference (class, string, array).</summary>
17+
Ref,
18+
/// <summary>Interior pointer (byref).</summary>
19+
Interior,
20+
/// <summary>Value type that may contain embedded GC references.</summary>
21+
Other,
22+
}
23+
924
public interface ISignatureDecoder : IContract
1025
{
1126
static string IContract.Name { get; } = nameof(SignatureDecoder);
27+
1228
TypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, TypeHandle ctx) => throw new NotImplementedException();
29+
30+
/// <summary>
31+
/// Decodes a method's signature for GC scanning purposes, classifying each parameter
32+
/// as a GC reference, interior pointer, value type, or non-GC type.
33+
/// Handles ELEMENT_TYPE_INTERNAL via the runtime type system.
34+
/// </summary>
35+
MethodSignature<GcTypeKind> DecodeMethodSignatureForGC(BlobHandle blobHandle, ModuleHandle moduleHandle) => throw new NotImplementedException();
1336
}
1437

1538
public readonly struct SignatureDecoder : ISignatureDecoder

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs renamed to src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Signature/GcSignatureTypeProvider.cs

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,27 @@
33

44
using System.Collections.Immutable;
55
using System.Reflection.Metadata;
6+
using Microsoft.Diagnostics.DataContractReader.Contracts;
67

7-
namespace Microsoft.Diagnostics.DataContractReader.Contracts.StackWalkHelpers;
8-
9-
/// <summary>
10-
/// Classification of a signature type for GC scanning purposes.
11-
/// </summary>
12-
internal enum GcTypeKind
13-
{
14-
/// <summary>Not a GC reference (primitives, pointers).</summary>
15-
None,
16-
/// <summary>Object reference (class, string, array).</summary>
17-
Ref,
18-
/// <summary>Interior pointer (byref).</summary>
19-
Interior,
20-
/// <summary>Value type that may contain embedded GC references.</summary>
21-
Other,
22-
}
8+
namespace Microsoft.Diagnostics.DataContractReader.SignatureHelpers;
239

2410
/// <summary>
2511
/// Classifies signature types for GC scanning purposes.
26-
/// Implements <see cref="ISignatureTypeProvider{TType, TGenericContext}"/> for use
27-
/// with SRM's <see cref="SignatureDecoder{TType, TGenericContext}"/>.
12+
/// Implements <see cref="IRuntimeSignatureTypeProvider{TType, TGenericContext}"/> which
13+
/// is a superset of SRM's <see cref="ISignatureTypeProvider{TType, TGenericContext}"/>,
14+
/// adding support for <c>ELEMENT_TYPE_INTERNAL</c>.
2815
/// </summary>
2916
internal sealed class GcSignatureTypeProvider
30-
: ISignatureTypeProvider<GcTypeKind, object?>
17+
: IRuntimeSignatureTypeProvider<GcTypeKind, object?>
3118
{
32-
public static readonly GcSignatureTypeProvider Instance = new();
19+
private readonly Target _target;
20+
private readonly ModuleHandle _moduleHandle;
21+
22+
public GcSignatureTypeProvider(Target target, ModuleHandle moduleHandle)
23+
{
24+
_target = target;
25+
_moduleHandle = moduleHandle;
26+
}
3327

3428
public GcTypeKind GetPrimitiveType(PrimitiveTypeCode typeCode)
3529
=> typeCode switch
@@ -60,5 +54,41 @@ public GcTypeKind GetGenericInstantiation(GcTypeKind genericType, ImmutableArray
6054
public GcTypeKind GetGenericTypeParameter(object? genericContext, int index) => GcTypeKind.Ref;
6155
public GcTypeKind GetFunctionPointerType(MethodSignature<GcTypeKind> signature) => GcTypeKind.None;
6256
public GcTypeKind GetModifiedType(GcTypeKind modifier, GcTypeKind unmodifiedType, bool isRequired) => unmodifiedType;
57+
public GcTypeKind GetInternalModifiedType(Target target, TargetPointer typeHandlePointer, GcTypeKind unmodifiedType, bool isRequired) => unmodifiedType;
6358
public GcTypeKind GetPinnedType(GcTypeKind elementType) => elementType;
59+
60+
public GcTypeKind GetInternalType(Target target, TargetPointer typeHandlePointer)
61+
{
62+
if (typeHandlePointer == TargetPointer.Null)
63+
return GcTypeKind.None;
64+
65+
try
66+
{
67+
IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem;
68+
TypeHandle th = rts.GetTypeHandle(typeHandlePointer);
69+
CorElementType corType = rts.GetSignatureCorElementType(th);
70+
71+
return corType switch
72+
{
73+
CorElementType.Void or CorElementType.Boolean or CorElementType.Char
74+
or CorElementType.I1 or CorElementType.U1
75+
or CorElementType.I2 or CorElementType.U2
76+
or CorElementType.I4 or CorElementType.U4
77+
or CorElementType.I8 or CorElementType.U8
78+
or CorElementType.R4 or CorElementType.R8
79+
or CorElementType.I or CorElementType.U
80+
or CorElementType.FnPtr or CorElementType.Ptr
81+
=> GcTypeKind.None,
82+
83+
CorElementType.Byref => GcTypeKind.Interior,
84+
CorElementType.ValueType => GcTypeKind.Other,
85+
86+
_ => GcTypeKind.Ref,
87+
};
88+
}
89+
catch
90+
{
91+
return GcTypeKind.Ref;
92+
}
93+
}
6494
}

0 commit comments

Comments
 (0)