Sitelet https://github.com/dotnet/runtime/pull/134966
Skip to content

Remove CoreCLR Reflection.Emit's ceefilegen dependency - #134966

Merged
jkoritzinsky merged 5 commits into
mainfrom
dev/jkoritzinsky/reflection-emit-rva-storage
Oct 2, 2026
Merged

jkoritzinsky merged 5 commits into
mainfrom
dev/jkoritzinsky/reflection-emit-rva-storage

Conversation

@jkoritzinsky

@jkoritzinsky jkoritzinsky commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

CoreCLR's in-memory Reflection.Emit implementation uses PE-style sections and relocation records just to retain method IL and FieldRVA bytes. Store those bytes directly in loader-owned memory and reuse the existing token-to-address map, so shared and static CoreCLR no longer need to link ceefgen.

Changes

  • Allocate emitted IL and aligned, zero-initialized field data on the module's loader allocator. Preserve IL/EH encoding and collectible field-data lifetime tracking.
  • Use MethodDef tokens as non-address values in the dynamic module's metadata RVA column, retaining the nonzero-body invariant. Resolve field data using the existing FIELD_OFFSET_DYNAMIC_RVA sentinel and token map, including reflection's fast field-access path.
  • Remove generator ownership, PE section allocation, and native/managed token-relocation bookkeeping. Preserve ILAsm's separate ceefgen_nohost dependency and PE-writing implementation.
  • Add emission, field-content/alignment, and diagnostic coverage. Update the canonical cDAC descriptor descriptions and generated documentation.

Existing token-aware diagnostic paths resolve the new storage. Raw ISOSDacInterface.GetILForModule support for Reflection.Emit remains unchanged: it is unsupported by the native DAC.

Validation

Windows x64 Release and Checked builds passed. Local coverage includes:

  • All 2,968 Reflection.Emit, ILGeneration, and Lightweight library tests.
  • 408 cDAC Loader/MethodTable tests, including mock 32/64-bit and little/big-endian layouts and legacy-facing entry points.
  • 18 runtime reflection wrappers, collectible byref/span lifetime coverage, profiler ModuleLoad and ReJIT tests, and 24 existing EnC tests.
  • The 12 new behavior-preservation cases on both the frozen baseline and changed Release runtime.
  • Documentation generation/drift checks and actual Checked/Release Ninja link inputs confirming that shared/static CoreCLR exclude ceefilegen while ILAsm retains it.

Other runtime architectures and metadata-updater-disabled builds were not run. The pre-existing commented-out EnC TestAddFieldRVA case was left unchanged and was not included in the EnC count.

Local measurements and trade-off

Dependency-free, ad hoc Windows x64 Release harness; A/B/B/A process order, 18 measurements per operation per host, and tiered compilation disabled for both. These are shared-machine measurements, not BenchmarkDotNet results.

The slowdown below is limited to the non-intrinsic runtime fallback path for FieldRVA data defined by System.Reflection.Emit. It is not a loss of intrinsic expansion: these benchmark cases use the fallback in both the baseline and changed builds.

Metric Baseline Changed
coreclr.dll size 4,835,840 bytes 4,823,552 bytes (-12 KiB)
Release browser dotnet.native.wasm size 4,711,053 bytes 4,700,549 bytes (-10,504 bytes, -0.223%)
Release browser dotnet.native.wasm Brotli q11 size 1,350,926 bytes 1,348,055 bytes (-2,871 bytes, -0.213%)
Release browser dotnet.native.wasm code section 3,667,990 bytes 3,658,132 bytes (-9,858 bytes, -0.269%)
Release browser dotnet.native.wasm data section 1,016,977 bytes 1,016,475 bytes (-502 bytes, -0.049%)
Release browser dotnet.native.wasm defined functions 9,596 9,556 (-40)
Managed allocation for a 32-method emission workload ~36.1 KB/module ~32.7 KB/module
Non-intrinsic InitializeArray, SRE field 141.563 ns 153.904 ns (+8.7%)
Non-intrinsic CreateSpan, SRE field 142.519 ns 155.601 ns (+9.2%)

Module-creation medians were approximately 0.3%-4.1% lower across four workloads. Process-private-memory growth while retaining emitted modules was approximately 24%-39% lower; this is not a pure native-allocation metric.

The slow benchmark supplies field handles obtained through reflection and reuses an existing array. Its fallback now resolves emitted field data through a locked token-map lookup instead of unlocked section-offset translation. Follow-up disassembly confirmed identical managed fallback instruction sequences in both builds.

Intrinsic-friendly ldtoken/CreateSpan and constant-size newarr/dup/ldtoken/InitializeArray patterns still expand to direct data access in both builds, with no per-invocation token lookup; the address is resolved at JIT time. Ordinary PE-backed fields also retain their existing lookup path. Follow-up controls for those cases were approximately unchanged, so the slowdown percentages above do not apply to them.

Note

This implementation and PR description were prepared with GitHub Copilot.

Store emitted IL and FieldRVA data in loader-owned buffers indexed by the existing dynamic token map. Generalize dynamic field resolution, remove PE section and token relocation bookkeeping, and preserve ILAsm's no-host generator.

Add emitted-body, field-data, and diagnostic coverage and update the canonical cDAC descriptor descriptions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@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: @agocke
See info in area-owners.md if you want to be subscribed.

Remove the Reflection.Emit exception from the image-backed RVA assertion now that emitted fields use the preceding dynamic-token branch.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jkoritzinsky jkoritzinsky added the size-reduction Issues impacting final app size primary for size sensitive workloads label Sep 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'size-reduction': @eerhardt, @SamMonoRT
See info in area-owners.md if you want to be subscribed.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Comment thread src/coreclr/vm/ceeload.h
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Regenerate browser and WASI call-helper tables after shortening the Reflection.Emit SetMethodIL QCall signature. The missing interpreter thunk caused null-function traps in browser CoreCLR library tests.

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

Copy link
Copy Markdown
Member Author

/ba-g cdac stress test failures are all recognized, but they still emit a build failure that itself isn't recognized by a KBE.

@jkoritzinsky
jkoritzinsky disabled auto-merge October 2, 2026 23:07
@jkoritzinsky
jkoritzinsky merged commit 35bc6da into main Oct 2, 2026
176 of 181 checks passed
@jkoritzinsky
jkoritzinsky deleted the dev/jkoritzinsky/reflection-emit-rva-storage branch October 2, 2026 23:07
@jkoritzinsky
jkoritzinsky restored the dev/jkoritzinsky/reflection-emit-rva-storage branch October 2, 2026 23:07
@jkoritzinsky
jkoritzinsky deleted the dev/jkoritzinsky/reflection-emit-rva-storage branch October 2, 2026 23:08
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-VM-coreclr size-reduction Issues impacting final app size primary for size sensitive workloads

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants