Uh oh!
There was an error while loading. Please reload this page.
Report CoreCLR Write Barriers And Code-Heap Stubs In Traces - #132190
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
There was a problem hiding this comment.
Pull request overview
This PR expands runtime symbol reporting for executable code that’s generated/allocated outside normal JITted methods, so tracing consumers can attribute those code ranges in ETW/EventPipe and PerfMap outputs. It does this by emitting helper-style method events for copied write barriers and code-heap stub/code-fragment blocks, and by improving CodeHeapIterator’s ability to surface bounded stub ranges during enumeration/rundown.
Changes:
- Add reporting/enumeration of copied write-barrier code ranges for ETW enumeration and PerfMap (including replay during method enumeration).
- Teach
CodeHeapIteratorto identify stub code blocks and provide bounded sizes + kinds for logging. - Extend the EventPipe rundown validation test to generate VSD activity and validate helper events appear in live + rundown streams.
Show a summary per file
| File | Description |
|---|---|
| src/tests/tracing/eventpipe/rundownvalidation/rundownvalidation.cs | Generates VSD activity and validates helper-style stub/write-barrier events appear in live + rundown method events. |
| src/coreclr/vm/threads.h | Renames/init entrypoint and adds declarations for copied write-barrier reporting helpers. |
| src/coreclr/vm/threads.cpp | Implements enumeration/reporting of copied write barriers to PerfMap and ETW enumeration. |
| src/coreclr/vm/perfmap.cpp | Emits copied write barriers and stub-block ranges when generating an on-demand PerfMap. |
| src/coreclr/vm/eventtrace.cpp | Extends helper event emission to support different enumeration event types and reports stub blocks + copied write barriers during enumeration. |
| src/coreclr/vm/dynamicmethod.cpp | Ensures heap list entries for host code heaps carry a loader allocator pointer for filtered iteration. |
| src/coreclr/vm/codeman.h | Adds wide-string stub-kind names, stub-kind/size accessors on CodeHeapIterator, and moves small-block threshold to a shared constant. |
| src/coreclr/vm/codeman.cpp | Updates CodeHeapIterator to snapshot heap ends, identify stub code blocks, and report stub blocks via PerfMap + ETW helper events. |
| src/coreclr/vm/ceemain.cpp | Calls the new tracing-data initializer during startup. |
| src/coreclr/inc/eventtracebase.h | Updates/moves SendHelperEvent declaration to support passing enumeration options. |
Review details
- Files reviewed: 10/10 changed files
- Comments generated: 0
- Review effort level: Lite
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Uh oh!
There was an error while loading. Please reload this page.
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
brianrob
commented
Aug 13, 2026
/azp run runtime Note This rerun request was generated by GitHub Copilot after Build Analysis identified unrelated infrastructure timeouts and known test failures. |
|
No pipelines are associated with this pull request. |
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Review details
Suppressed comments (1)
src/tests/tracing/eventpipe/rundownvalidation/rundownvalidation.cs:111
- The test currently requires write-barrier helper events to be present and valid (ValidateHelperEvents(rundownWriteBarriers)), but copied write barriers are not necessarily enabled. In CoreCLR, write-barrier copying is gated by CLRConfig::UNSUPPORTED_UseGCWriteBarrierCopy and defaults to disabled (src/coreclr/vm/eeconfig.cpp:110 sets fIsWriteBarrierCopyEnabled = false; src/coreclr/vm/eeconfig.cpp:531 sets it based on the config switch). When the copy is disabled, ReportCopiedWriteBarriers* won’t emit any helper events, rundownWriteBarriers stays empty, and this test will fail on otherwise-correct builds.
Consider validating write-barrier helpers only when the events are actually present (or otherwise gating the expectation on a detectable condition).
bool hasValidCoreClrHelpers =
!PlatformDetection.IsCoreCLR ||
!RuntimeFeature.IsDynamicCodeCompiled ||
(ValidateHelperEvents(liveStubBlocks) &&
ValidateHelperEvents(rundownStubBlocks) &&
ValidateHelperEvents(rundownWriteBarriers) &&
HaveMatchingStubBlocks(liveStubBlocks, rundownStubBlocks));
- Files reviewed: 11/11 changed files
- Comments generated: 0 new
- Review effort level: Lite
davidwrighton
commented
Aug 13, 2026
LGTM, but I want @hoyosjs to review as well before signoff. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
Uh oh!
There was an error while loading. Please reload this page.
brianrob
commented
Aug 17, 2026
/ba-g Current failures are unrelated known test failures: HttpListener timeout #132336 on both Windows checked legs, browser-Wasm bestfit-finalize #132107, and browser-Wasm ContextualReflection preemptive-GC assertion #131925. The affected tests and subsystems are outside this PR's ETW/stub changes. Note This Build Analysis override rationale was generated by GitHub Copilot. |
brianrob
commented
Aug 17, 2026
@hoyosjs this one should be ready for review again. Thanks. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
There was a problem hiding this comment.
Review details
Suppressed comments (2)
src/tests/tracing/eventpipe/rundownvalidation/rundownvalidation.cs:449
- The EventSource events are defined as JumpStubCollectionStart/JumpStubCollectionStop, but the trace parsing looks for "JumpStubCollection/Start" (task/opcode-style naming). Without explicitly setting EventOpcode and/or EventAttribute.Name, this comparison likely never matches, leaving collectionStart as NaN and causing the unload-range validation to fail.
if (eventData.EventName == "JumpStubCollection/Start")
{
collectionStart = eventData.TimeStampRelativeMSec;
}
src/tests/tracing/eventpipe/rundownvalidation/rundownvalidation.cs:453
- Same issue as the Start event: the parser looks for "JumpStubCollection/Stop" but the EventSource event is JumpStubCollectionStop unless an explicit Stop opcode/name is set.
else if (eventData.EventName == "JumpStubCollection/Stop")
{
collectionStop = eventData.TimeStampRelativeMSec;
}
- Files reviewed: 11/11 changed files
- Comments generated: 0 new
- Review effort level: Lite
hoyosjs
left a comment
There was a problem hiding this comment.
Other than the test issue this seems good (assuming we are ok with the rundown event being an approximation, which seems fair for a trace/profiling effort - I don't see the tradeoff in storing this information elsewhere).
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8ec89d46-dd0a-4373-8c4b-9ccdabfdecc2
There was a problem hiding this comment.
Copilot review overview
Review tier: Lite
Findings: None
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/tests/tracing/eventpipe/rundownvalidation/rundownvalidation.cs:483
- If the JumpStubCollection Start/Stop markers are missing (e.g., due to EventName differences) or Stop precedes Start,
collectionStart/collectionStopremainNaN/invalid andGetEventsInRangewill silently return an empty set, causing a failure that’s hard to diagnose. Add an explicit validation of the marker timestamps before filtering unload events and log a clear error when they’re missing/invalid.
List<HelperEvent> reclaimedJumpStubBlocks =
GetEventsInRange(unloadedJumpStubBlocks, collectionStart, collectionStop);
Logger.logger.Log("LCG jump-stub loads: " + loadedJumpStubBlocks.Count);
Logger.logger.Log("LCG jump-stub unloads: " + reclaimedJumpStubBlocks.Count);
return HaveMatchingLoadForEveryUnload(loadedJumpStubBlocks, reclaimedJumpStubBlocks)
Summary
Improve symbol coverage for executable code generated outside normal JIT methods. This is in response to an internal customer that is capturing traces where large percentages of symbols are unresolvable and don't resolve to a module. Upon investigation, these symbols should resolve to the copied write barrier or one of several different kinds of stubs.
Coverage
MethodUnloadVerbose,MethodDCStartVerbose, andMethodDCEndVerbose.MethodLoadVerbose.MethodUnloadVerbose,MethodDCStartVerbose, andMethodDCEndVerbose.DOTNET_PerfMapStubGranularity.On-demand PerfMap generation uses blocks because individual allocations cannot be reconstructed during enumeration.
All ETW/EventPipe entries use
JitHelperMethodmetadata.Implementation Notes
CodeHeapIteratornow snapshots each heap’s end and uses per-heap lookahead to produce bounded, non-overlapping stub ranges. Jump-stub sizes use their existing allocation metadata; other code-fragment blocks use the bounded allocation extent.Copied write-barrier reporting derives targets from the configured JIT helper table.
This does not change stub layout, allocation size, alignment,
CodeHeaderadjacency, DAC contracts, or jump reachability.Note
This pull request description was created with GitHub Copilot.