Skip to content

[cDAC] Implement DacDbi APIs EnumerateClassFields and EnumerateInstantiationFields#128829

Open
Copilot wants to merge 4 commits into
mainfrom
copilot/create-plan-for-dacdbi-apis
Open

[cDAC] Implement DacDbi APIs EnumerateClassFields and EnumerateInstantiationFields#128829
Copilot wants to merge 4 commits into
mainfrom
copilot/create-plan-for-dacdbi-apis

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jun 1, 2026

  • Add EditAndContinue cDAC contract with API
IEnumerable<TargetPointer> EnumerateAddedFieldDescs(TypeHandle typeHandle, bool staticFields);

Adding the following RuntimeTypeSystem APIs:

    uint GetNumInstanceFieldBytes(TypeHandle typeHandle);
    bool IsFieldDescRVA(TargetPointer fieldDescPointer);
    bool IsFieldDescEnCNew(TargetPointer fieldDescPointer);

…h/alloc, full DEBUG validation)

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Copilot AI self-assigned this Jun 1, 2026
Copilot AI review requested due to automatic review settings June 1, 2026 02:15
Copilot AI review requested due to automatic review settings June 1, 2026 02:15
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

Copilot AI review requested due to automatic review settings June 1, 2026 02:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

The PR description frames this as a small follow-up cleanup ("refactor two file-local FieldDataAccumulator helpers to use the existing generic CallbackAccumulator<FieldData> and revert an unnecessary DAC/DBI protocol counter bump"), but the actual diff is a much larger change that also lands the DacDbi FieldData callback-based protocol, the new cDAC IEditAndContinue contract, and supporting data descriptors.

Changes:

  • Replace IDacDbiInterface::GetClassInfo / GetInstantiationFieldInfo with callback-based EnumerateClassFields / EnumerateInstantiationFields (managed + native) and refactor rsclass.cpp / rstype.cpp to drive them via CallbackAccumulator<FieldData>; widen FieldData::m_fldInstanceOffset to ULONG64 and m_pFldStaticAddress to CORDB_ADDRESS.
  • Add a new cDAC IEditAndContinue contract (EnumerateAddedFieldDescs), new EnCEEClassData / EnCAddedFieldElement / UnorderedArrayBase Data classes + descriptors, Module.EnCClassList (optional FieldAddress), and supporting source-generator changes for nullable FieldAddress.
  • Expose GetNumInstanceFieldBytes / IsFieldDescRVA / IsFieldDescEnCNew on IRuntimeTypeSystem, add EEClass.BaseSizePadding, extract CUnorderedArrayBase so cDAC can read it, and add mocks + xUnit tests for the new EnC contract.
Show a summary per file
File Description
src/coreclr/inc/dacdbi.idl Replace GetClassInfo/GetInstantiationFieldInfo with Enumerate* callback-based variants; drop DacDbiArrayList_FieldData/ClassInfo decls.
src/coreclr/debug/inc/dacdbiinterface.h New FP_FIELDDATA_CALLBACK typedef and EnumerateClassFields / EnumerateInstantiationFields virtuals; updated docs.
src/coreclr/debug/inc/dacdbistructures.h Widen m_fldInstanceOffset to ULONG64 and m_pFldStaticAddress to CORDB_ADDRESS; update setter signatures.
src/coreclr/debug/inc/dacdbistructures.inl Adjust FieldData inline accessors to match new CORDB_ADDRESS/ULONG64 types.
src/coreclr/debug/daccess/dacdbiimpl.h Replace GetClassInfo/GetInstantiationFieldInfo decls; change CollectFields to callback form; drop GetTotalFieldCount/InitClassData.
src/coreclr/debug/daccess/dacdbiimpl.cpp Implement callback-based Enumerate*; update ComputeFieldData to use CORDB_ADDRESS; remove preallocation/count logic.
src/coreclr/debug/di/rsclass.cpp Drive EnumerateClassFields via CallbackAccumulator<FieldData> and Init the field list from acc.items.
src/coreclr/debug/di/rstype.cpp Same refactor for EnumerateInstantiationFields.
src/coreclr/inc/utilcode.h Extract CUnorderedArrayBase (count + TADDR table) from CUnorderedArrayWithAllocator and add cdac_data shim.
src/coreclr/vm/encee.h Add cdac_data for EnCEEClassData and EnCAddedFieldElement.
src/coreclr/vm/ceeload.h Add cdac_data<Module>::EnCClassList under FEATURE_METADATA_UPDATER.
src/coreclr/vm/class.h Add cdac_data<EEClass>::BaseSizePadding.
src/coreclr/vm/datadescriptor/datadescriptor.inc Add UnorderedArrayBase, EnCEEClassData, EnCAddedFieldElement descriptors; EEClass.BaseSizePadding; FieldOffsetNewEnc global; EditAndContinue contract entry.
.../Abstractions/Contracts/IEditAndContinue.cs New contract interface (EnumerateAddedFieldDescs) and empty struct.
.../Abstractions/Contracts/IRuntimeTypeSystem.cs Add GetNumInstanceFieldBytes, IsFieldDescRVA, IsFieldDescEnCNew; make fieldDef nullable on GetFieldDescOffset.
.../Abstractions/ContractRegistry.cs Expose EditAndContinue accessor.
.../Contracts/CoreCLRContracts.cs Register EditAndContinue v1.
.../Contracts/Contracts/EditAndContinue_1.cs New v1 implementation enumerating EnC-added FieldDescs.
.../Contracts/Contracts/RuntimeTypeSystem_1.cs Implement GetNumInstanceFieldBytes/IsFieldDescEnCNew; promote IsFieldDescRVA to interface; null-handle big-RVA fieldDef.
.../Contracts/Data/{Module,EEClass,EnCEEClassData,EnCAddedFieldElement,UnorderedArrayBase}.cs New Data classes / fields backing the EnC descriptors.
.../Contracts/DataType.cs / Constants.cs New DataType values and FieldOffsetNewEnc global.
.../DataGenerator/Parser.cs, Emitter.cs Source-gen support for optional/nullable [FieldAddress] properties.
.../Legacy/Dbi/{IDacDbiInterface.cs,DacDbiImpl.cs} Define FieldData struct; implement new managed Enumerate* with optional debug-only legacy validation.
src/native/managed/cdac/tests/... New mock infrastructure (MockDescriptors.EditAndContinue.cs), EnC contract xUnit tests, and TestOptionalFieldAddr data-generator tests.
docs/design/datacontracts/{EditAndContinue,RuntimeTypeSystem}.md Document the new contract and the new IRuntimeTypeSystem APIs/globals.

Copilot's findings

  • Files reviewed: 36/36 changed files
  • Comments generated: 1

Comment thread src/coreclr/debug/inc/dacdbistructures.h
Copilot stopped work on behalf of rcj1 due to an error June 1, 2026 02:54
Copilot AI requested a review from rcj1 June 1, 2026 02:54
Copilot AI review requested due to automatic review settings June 1, 2026 18:23
@rcj1 rcj1 changed the title Refactor FieldData accumulators in DI to CallbackAccumulator&lt;FieldData&gt; [cDAC] Implement DacDbi APIs EnumerateClassFields and EnumerateInstantiationFields Jun 1, 2026
@rcj1 rcj1 marked this pull request as ready for review June 1, 2026 18:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 39/39 changed files
  • Comments generated: 5

Comment on lines 1704 to +1708
// this may be called multiple times. Each call will discard previous values in m_fieldList and reinitialize
// the list with updated information
RSLockHolder lockHolder(pProcess->GetProcessLock());
IfFailThrow(pProcess->GetDAC()->GetInstantiationFieldInfo(m_pClass->GetModule()->GetRuntimeAssembly(),

CallbackAccumulator<FieldData> acc;
Comment on lines +1895 to +1896
// Mirrors native: storage not yet available; carry the FieldDesc pointer through
// m_vmFieldDesc but leave all "is" flags false.
Comment on lines +267 to +269
bool isNullable = prop.Type is INamedTypeSymbol named
&& named.IsGenericType
&& named.ConstructedFrom.ToDisplayString() == "System.Nullable<T>";
Comment on lines +2109 to 2112
if (DWord2 == _target.ReadGlobal<uint>("FieldOffsetBigRVA") && fieldDef.HasValue)
{
return (uint)fieldDef.GetRelativeVirtualAddress();
return (uint)fieldDef.Value.GetRelativeVirtualAddress();
}
Copy link
Copy Markdown
Member

@noahfalk noahfalk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked good other than a few comments inline.

@@ -0,0 +1,64 @@
# Contract EditAndContinue
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Contract EditAndContinue
# Contract RuntimeMutableTypeSystem

Naming nit: I believe we have scenarios other than ENC (such as HotReload) that can modify types on the fly too.

@@ -0,0 +1,64 @@
# Contract EditAndContinue

This contract exposes the runtime's Edit-and-Continue (EnC) bookkeeping.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This contract exposes the runtime's Edit-and-Continue (EnC) bookkeeping.
This contract exposes runtime type system information about changes that occured after the initial type load, such as from ENC or HotReload.

bool IsFieldDescThreadStatic(TargetPointer fieldDescPointer);
bool IsFieldDescStatic(TargetPointer fieldDescPointer);
bool IsFieldDescRVA(TargetPointer fieldDescPointer);
bool IsFieldDescEnCNew(TargetPointer fieldDescPointer);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we put this in the ENC contract? A runtime that doesn't implement the ENC contract shouldn't have discoverable ENC FieldDescs.


### FieldDesc

The version 1 FieldDesc APIs depend on the following globals:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment implies we have a separately versioning FieldDesc contract but I don't believe we do right? Unless we plan to define a separate contract this sounds like it should get merged with other RuntimeTypeSystem references.

// Free the chunk of memory.
if (m_pTable != NULL)
ALLOCATOR::Free(this, m_pTable);
if (m_pTable != (TADDR)NULL)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than modify all these members is anything stopping us from leaving m_pTable conditionally typed as T*/TADDR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants