Skip to content

Commit c9ce936

Browse files
Max CharlambCopilot
andcommitted
[cDAC] Demonstrate Lock as a cross-source IData<T> type
Per Jan's request on PR dotnet#127310 (dotnet#127310 (comment)), this commit shows what it takes to add System.Threading.Lock to the native cdac descriptor. Under the new fallback design, the IData<T> class stays in one place and gains BOTH sources via a per-field candidate-name cascade -- not a choose-one-source decision. Runtime side (3 files, matches the throwaway branch shared with Jan): - `src/coreclr/vm/object.h` -- `class LockObject : public Object` plus `cdac_data<LockObject>` template exposing the offsets. - `src/coreclr/vm/datadescriptor/datadescriptor.inc` -- new `CDAC_TYPE_BEGIN(Lock)` block with T_INT32 `OwningThreadId` and T_UINT32 `State` / `RecursionCount` fields. - `src/coreclr/vm/corelib.h` -- `DEFINE_CLASS_U(Threading, Lock, NoClass)` plus `DEFINE_FIELD_U(...)` for the three fields. Managed side (1 file change vs the throwaway branch's 2): - `DataType.cs` -- add `Lock` enum member. - `Data/Managed/Lock.cs` -- ONE attribute change. The class gains `nameof(DataType.Lock)` alongside `ManagedFullName` and each `[Field]` lists both candidate names: [CdacType(nameof(DataType.Lock), ManagedFullName = "System.Threading.Lock")] internal sealed partial class Lock : IData<Lock> { [Field("State", "_state")] public uint State { get; } [Field("OwningThreadId", "_owningThreadId")] public int OwningThreadId { get; } [Field("RecursionCount", "_recursionCount")] public uint RecursionCount { get; } } The cdac runtime generator emits a `LayoutPairResolver.Resolve` call that picks up both sources; each field's read tries `"State"` against the native cdac descriptor first, falling through to `"_state"` against the managed type metadata when needed. No class move / namespace change / caller update. Contrast with the throwaway branch (62223d6...b3dfdc8) which had to delete `Data/Managed/Lock.cs` and add a new `Data/Lock.cs` with a hand-written ctor and `init` properties, then update `Contracts/SyncBlock_1.cs` to reference the new namespace. The new design needs only the runtime-side `LockObject` plumbing + the single attribute decoration. Build clean; full cdac test suite still 2206 passing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2440300 commit c9ce936

5 files changed

Lines changed: 38 additions & 4 deletions

File tree

src/coreclr/vm/corelib.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,10 @@ DEFINE_FIELD(MONITOR, CONDITION_TABLE, s_conditionTable)
630630
DEFINE_METHOD(MONITOR, SYNCHRONIZED_METHOD_ENTER, SynchronizedMethodEnter, SM_Obj_RefBool_RetVoid)
631631
DEFINE_METHOD(MONITOR, SYNCHRONIZED_METHOD_EXIT, SynchronizedMethodExit, SM_Obj_RefBool_RetVoid)
632632

633+
DEFINE_CLASS_U(Threading, Lock, NoClass)
634+
DEFINE_FIELD_U(_owningThreadId, LockObject, _owningThreadId)
635+
DEFINE_FIELD_U(_state, LockObject, _state)
636+
DEFINE_FIELD_U(_recursionCount, LockObject, _recursionCount)
633637
DEFINE_CLASS(LOCK, Threading, Lock)
634638
DEFINE_FIELD(LOCK, OWNING_THREAD_ID, _owningThreadId)
635639
DEFINE_FIELD(LOCK, STATE, _state)

src/coreclr/vm/datadescriptor/datadescriptor.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,13 @@ CDAC_TYPE_FIELD(String, T_POINTER, m_FirstChar, cdac_data<StringObject>::m_First
180180
CDAC_TYPE_FIELD(String, T_UINT32, m_StringLength, cdac_data<StringObject>::m_StringLength)
181181
CDAC_TYPE_END(String)
182182

183+
CDAC_TYPE_BEGIN(Lock)
184+
CDAC_TYPE_INDETERMINATE(Lock)
185+
CDAC_TYPE_FIELD(Lock, T_INT32, OwningThreadId, cdac_data<LockObject>::_owningThreadId)
186+
CDAC_TYPE_FIELD(Lock, T_UINT32, State, cdac_data<LockObject>::_state)
187+
CDAC_TYPE_FIELD(Lock, T_UINT32, RecursionCount, cdac_data<LockObject>::_recursionCount)
188+
CDAC_TYPE_END(Lock)
189+
183190
CDAC_TYPE_BEGIN(ContinuationObject)
184191
CDAC_TYPE_SIZE(sizeof(ContinuationObject))
185192
CDAC_TYPE_END(ContinuationObject)

src/coreclr/vm/object.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,28 @@ struct cdac_data<StringObject>
877877
static constexpr size_t m_StringLength = offsetof(StringObject, m_StringLength);
878878
};
879879

880+
// Native mirror of the managed System.Threading.Lock class layout. This is used
881+
// only by the cDAC data descriptor to expose the offsets of Lock's relevant
882+
// instance fields. The field order/types must be kept in sync with the managed
883+
// declaration in System.Private.CoreLib (System/Threading/Lock.cs).
884+
class LockObject : public Object
885+
{
886+
private:
887+
INT32 _owningThreadId;
888+
UINT32 _state;
889+
UINT32 _recursionCount;
890+
891+
friend struct ::cdac_data<LockObject>;
892+
};
893+
894+
template<>
895+
struct cdac_data<LockObject>
896+
{
897+
static constexpr size_t _owningThreadId = offsetof(LockObject, _owningThreadId);
898+
static constexpr size_t _state = offsetof(LockObject, _state);
899+
static constexpr size_t _recursionCount = offsetof(LockObject, _recursionCount);
900+
};
901+
880902
/*================================GetEmptyString================================
881903
**Get a reference to the empty string. If we haven't already gotten one, we
882904
**query the String class for a pointer to the empty string that we know was

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Managed/Lock.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33

44
namespace Microsoft.Diagnostics.DataContractReader.Data.Managed;
55

6-
[CdacType(ManagedFullName = "System.Threading.Lock")]
6+
[CdacType(nameof(DataType.Lock), ManagedFullName = "System.Threading.Lock")]
77
internal sealed partial class Lock : IData<Lock>
88
{
9-
[Field("_state")]
9+
[Field("State", "_state")]
1010
public uint State { get; }
1111

12-
[Field("_owningThreadId")]
12+
[Field("OwningThreadId", "_owningThreadId")]
1313
public int OwningThreadId { get; }
1414

15-
[Field("_recursionCount")]
15+
[Field("RecursionCount", "_recursionCount")]
1616
public uint RecursionCount { get; }
1717
}

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/DataType.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public enum DataType
8484
ManagedObjectWrapperLayout,
8585
ComWrappersVtablePtrs,
8686
String,
87+
Lock,
8788
MethodDesc,
8889
MethodDescChunk,
8990
MethodDescCodeData,

0 commit comments

Comments
 (0)