Skip to content

Make custom IData initializers lazy - #131763

Merged
max-charlamb merged 1 commit into
dotnet:mainfrom
max-charlamb:cdac-lazy-property-initializers
Aug 3, 2026
Merged

Make custom IData initializers lazy#131763
max-charlamb merged 1 commit into
dotnet:mainfrom
max-charlamb:cdac-lazy-property-initializers

Conversation

@max-charlamb

Copy link
Copy Markdown
Member

Summary

This changes custom IData initialization from one eager OnInit hook to named, per-property lazy initializer methods.

IData generation

  • Add [CustomInit(nameof(Method))] for properties requiring custom read logic.
  • Generate lazy property getters that invoke and memoize the named initializer on first access.
  • Keep generated writable fields limited to [Field(Writable = true)] properties.
  • Add a descriptor-only TableRW IData type so its generated GetSize method is used when indexing metadata tables.

Usage analysis

  • Put DataDescriptorDependency and UsesDataDescriptorTypeSize annotations on custom initializer methods.
  • Record declared initializer dependencies while continuing to analyze the initializer body for globals, helper calls, and nested IData property reads.
  • Avoid treating EnsureAllFieldsRead as a complete dependency summary for types with custom initializers.

IData implementations

  • Convert existing OnInit implementations to named per-property initializer methods.
  • Preserve optional-field behavior and defer custom reads until the corresponding property is accessed.

Documentation and tests

  • Document named custom initializers and method-level dependency annotations.
  • Regenerate contract usage documentation to reflect property-level lazy reads.
  • Add generator and usage-analysis coverage for lazy initialization, memoization, named methods, and combined declared/inferred dependencies.

Testing

  • Microsoft.Diagnostics.DataContractReader.Contracts build
  • DataGenerator.Tests: 46 passed
  • CdacUsageGraph.Tests: 86 passed
  • Usage.Tests: 4 passed
  • Microsoft.Diagnostics.DataContractReader.Tests: 3207 passed, 16 skipped
  • CdacUsageGraph docs --check

Note

This pull request description was generated with GitHub Copilot.

Replace eager OnInit hooks with named per-property initializers and teach CdacUsageGraph to combine declared initializer dependencies with inferred body usage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ac4f2b2a-736b-4295-b586-50887eabfc60
Copilot AI review requested due to automatic review settings August 3, 2026 18:47
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@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.

@max-charlamb
max-charlamb requested a review from rcj1 August 3, 2026 18:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors cDAC IData custom initialization from a single eager OnInit hook to named, per-property lazy initializer methods (via a new [CustomInit] attribute), and updates the usage-analysis tooling/tests/docs accordingly.

Changes:

  • Introduces [CustomInit(nameof(Method))] and generator support to emit lazy, memoized getters that call an author-provided initializer method.
  • Updates CdacUsageGraph to treat initializer methods as dependency-bearing while still walking their bodies for inferred globals/helper/property reads.
  • Converts many existing IData implementations (Contracts/Data) and updates design docs + generator/usage tests for the new model.

Reviewed changes

Copilot reviewed 48 out of 48 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/native/managed/cdac/tools/CdacUsageGraph/tests/CdacUsageGraph.Tests/UsageWalkerIntegrationTests.cs Updates integration test to read deps from init methods
src/native/managed/cdac/tools/CdacUsageGraph/tests/CdacUsageGraph.Tests/DataTypeIndexTests.cs Updates/extends usage-index tests for custom init behavior
src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Semantic/CdacAttributeMatcher.cs Adds CustomInit symbol + custom-initializer detection
src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/CdacSymbols.cs Adds metadata name constant for CustomInitAttribute
src/native/managed/cdac/tools/CdacUsageGraph/src/CdacUsageGraph/Analysis/UsageWalker.cs Avoids short-circuiting body analysis for custom init methods
src/native/managed/cdac/tests/DataGenerator/TestTypes.cs Adds test type covering [CustomInit] generator behavior
src/native/managed/cdac/tests/DataGenerator/DataGeneratorTests.cs Adds tests for laziness/memoization and dependency behavior
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/UnwindInfo.cs Converts OnInit to per-property custom initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/TypeDesc.cs Converts OnInit to custom initializer returning base-derived value
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Thread.cs Splits eager init into per-property custom initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/TableSegment.cs Makes byte-buffer reads lazy via custom initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/TableRW.cs Adds descriptor-only type to surface generated GetSize
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/SyncTableEntry.cs Converts pointer-following init logic to lazy initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/SyncBlock.cs Splits OnInit reads into per-property lazy initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ReadyToRunInfo.cs Converts multiple pointer computations to lazy initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ReadyToRunCoreHeader.cs Converts section list materialization to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RCW.cs Converts interface-entry list read to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeSectionFragment.cs Converts tag-bit stripping logic to custom initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/PrecodeMachineDescriptor.cs Reworks optional fields/buffers into per-property lazy initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ObjectHandle.cs Splits handle/object computation into per-property initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/InterpreterRealCodeHeader.cs Converts pointer-following init logic to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/InstMethodHashTable.cs Converts entry enumeration to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/HandleTableMap.cs Converts bucket-pointer list read to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/HijackArgs.cs Converts register map materialization to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/Frame.cs Converts identifier read to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/CalleeSavedRegisters.cs Converts register map materialization to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Frames/ArgumentRegisters.cs Converts register map materialization to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/EETypeHashTable.cs Converts entry enumeration to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/DynamicStaticsInfo.cs Splits masked-pointer reads into lazy initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ComWrappersVtablePtrs.cs Converts pointer list materialization to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ComInterfaceEntry.cs Converts GUID materialization to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ComCallWrapper.cs Converts interface pointer array read to lazy initializer
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/CMiniMdRW.cs Uses TableRW.GetSize(target) via new descriptor-only type
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Bucket.cs Splits key/value array materialization into separate lazy initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ArrayListBase.cs Splits blocks vs element flattening into separate lazy initializers
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CdacAttributes.cs Adds new public [CustomInit] attribute definition
src/native/managed/cdac/IData.md Updates spec to describe [CustomInit] replacing OnInit
src/native/managed/cdac/gen/Parser.cs Parses [CustomInit]; refactors writable-field tracking
src/native/managed/cdac/gen/Model.cs Adds CustomInit member kind; extends member model
src/native/managed/cdac/gen/Emitter.cs Emits lazy getters that call named initializer methods
docs/design/datacontracts/WindowsErrorReporting.md Regenerates “data descriptors used” (removals/updates)
docs/design/datacontracts/SyncBlock.md Regenerates “data descriptors used” (removals/updates)
docs/design/datacontracts/StackWalk.md Regenerates “data descriptors used” (removals/updates)
docs/design/datacontracts/RuntimeMutableTypeSystem.md Regenerates “data descriptors used” (removals/updates)
docs/design/datacontracts/Object.md Regenerates “data descriptors used” (removals/updates)
docs/design/datacontracts/ExecutionManager.md Regenerates “data descriptors used” (additions/updates)
docs/design/datacontracts/EcmaMetadata.md Updates docs to include TableRW type-size usage
docs/design/datacontracts/data-descriptor-meanings.json Adds meaning entry for TableRW.Size

Comment thread src/native/managed/cdac/gen/Parser.cs

@rcj1 rcj1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm, good cleanup of generated dependencies.

@max-charlamb
max-charlamb marked this pull request as ready for review August 3, 2026 19:41
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@max-charlamb
max-charlamb enabled auto-merge (squash) August 3, 2026 20:21
@max-charlamb

Copy link
Copy Markdown
Member Author

/ba-g osx timeouts

@max-charlamb
max-charlamb merged commit 88956c7 into dotnet:main Aug 3, 2026
72 of 75 checks passed
@max-charlamb
max-charlamb deleted the cdac-lazy-property-initializers branch August 3, 2026 22:48
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.

3 participants