Conversation
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
|
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. |
|
Tagging subscribers to this area: @anicka-net, @dotnet/gc |
There was a problem hiding this comment.
Pull request overview
This PR refactors the CoreCLR GC handle write-barrier by moving the HndWriteBarrierWorker implementation into handletable.inl (so it can be inlined into its callers) and introduces a fast-path that avoids the handle-type lookup when the assigned target is in generation 0. This targets reduced overhead in hot handle assignment paths while keeping the GC/EE interface shape unchanged.
Changes:
- Inline
HndWriteBarrierWorkerintosrc/coreclr/gc/handletable.inland remove the out-of-line implementation fromhandletable.cpp. - Add an early-return fast-path in the worker to skip
HandleFetchType(handle)whenGetConvertedGeneration(value)is 0. - Move/adjust declarations (
GetConvertedGeneration,HandleFetchType) to be available to the inlined implementation and update includes accordingly.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/coreclr/gc/handletablepriv.h | Removes now-unneeded forward declarations previously used by the out-of-line worker. |
| src/coreclr/gc/handletable.inl | Adds the inlined HndWriteBarrierWorker implementation and updates HndAssignHandle to call it directly. |
| src/coreclr/gc/handletable.h | Adds handletableconstants.h include and exposes needed non-DAC prototypes for the inlined worker. |
| src/coreclr/gc/handletable.cpp | Removes the out-of-line HndWriteBarrierWorker implementation (now provided inline). |
| #ifndef DACCESS_COMPILE | ||
| int GetConvertedGeneration(_UNCHECKED_OBJECTREF obj); | ||
| uint32_t HandleFetchType(OBJECTHANDLE handle); | ||
| #endif // DACCESS_COMPILE |
There was a problem hiding this comment.
@copilot Move these functions to handletable.inl. Also, make sure that they get inlined
| @@ -224,4 +229,3 @@ FORCEINLINE BOOL HndIsNullOrDestroyedHandle(_UNCHECKED_OBJECTREF value) | |||
| #include "handletable.inl" | |||
There was a problem hiding this comment.
@copilot Delete #include "handletable.inl" in gcinternal.h - it is unnecessary since it is included here
There was a problem hiding this comment.
Removed in e4315e5. Note that handletable.h no longer includes handletable.inl (that include was moved to the .cpp files in a40af76): the inlined GetConvertedGeneration needs gc.h, and gc.h -> gchandletableimpl.h -> handletable.h is circular, so including the .inl from the header fails to compile. The .inl is included directly by the .cpp files that need it, and dropping it from gcinternal.h builds fine.
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/coreclr/gc/handletable.inl:68
- The comment describing async pinned handle behavior has a few grammar/wording issues (e.g., missing space after
//, “need”/“consider”). Updating it will make the intent clearer without changing behavior.
//OverlappedData need special treatment: because all user data pointed by it needs to be reported by this handle,
//its age is consider to be min age of the user data, to be simple, we just make it 0
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
src/coreclr/gc/handletablepriv.h:171
HandleFetchTypeinhandletable.inlreads the block type via rawuint8_t*indexing (segment[HANDLE_SEGMENT_BLOCK_TYPE_OFFSET + uBlock]). The existingoffsetofstatic_assert guards the offset, but the implementation also assumesrgBlockTypeelements are 1 byte. Adding a size check here makes that assumption explicit and prevents silent breakage if the field type ever changes.
static_assert(offsetof(_TableSegmentHeader, rgBlockType) == HANDLE_SEGMENT_BLOCK_TYPE_OFFSET);
src/coreclr/gc/handletable.inl:43
- New code in
handletable.inluses C-style casts when deriving segment pointers (e.g.,(uint8_t*)((uintptr_t)handle & HANDLE_SEGMENT_ALIGN_MASK)), while nearby code already usesreinterpret_cast. This is easy to fix and aligns with the repo's native guidance to prefer C++ casts.
uint8_t* barrier = (uint8_t*)((uintptr_t)handle & HANDLE_SEGMENT_ALIGN_MASK);
_ASSERTE(barrier);
uintptr_t offset = (uintptr_t)handle & HANDLE_SEGMENT_CONTENT_MASK;
_ASSERTE(offset >= HANDLE_HEADER_SIZE);
| #include "softwarewritewatch.h" | ||
| #include "handletable.h" | ||
| #include "handletable.inl" | ||
| #include "gcenv.inl" | ||
| #include "gceventstatus.h" |
Summary
Validation
instrsxarch.h.GCHandle.Targettest could not be built because test dependency assets have not been generated.Performance
Note
This pull request description was generated by AI/Copilot.