Reconcile ReleaseHolder, ComHolderPreemp, and ComHolderAnyMode#130373
Draft
AaronRobinsonMSFT wants to merge 2 commits into
Draft
Reconcile ReleaseHolder, ComHolderPreemp, and ComHolderAnyMode#130373AaronRobinsonMSFT wants to merge 2 commits into
AaronRobinsonMSFT wants to merge 2 commits into
Conversation
Converge the three COM-interface RAII holders onto the LifetimeHolder<Traits> pattern: - Retarget ReleaseHolder to LifetimeHolder<ReleaseHolderTraits<T>>, adopting ComHolderPreemp's preemptive-mode release semantics (the VM default). The Free() contract is MODE_PREEMPTIVE, gated on ENABLE_CONTRACTS_IMPL so non-VM consumers (utilcode, md, DAC, createdump) use a static-contract annotation. - Remove ComHolderPreemp entirely; ReleaseHolder replaces all uses. - Rename ComHolderAnyMode to ReleaseHolderAnyMode. - Relax both holders' static_assert from is_base_of<IUnknown, T> to a duck-typed "T has a Release() member" check (holder_detail::HasReleaseMethod), so ReleaseHolder can hold non-IUnknown types that expose Release(). Migrate all call sites off the legacy SpecializedWrapper API onto the LifetimeHolder API (Extract->Detach, Clear->Free, GetValue/IsNull/Assign/SuppressRelease removed). Read-after-suppress sites are restructured to detach into a raw pointer to preserve exception-safety and refcount behavior. BindAssemblySpec is refactored so the CoreLib singleton borrow no longer relies on SuppressRelease. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Tagging subscribers to this area: @agocke |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors CoreCLR’s COM / ref-counted RAII “holder” usage to converge on the LifetimeHolder<Traits> pattern: replacing legacy SpecializedWrapper APIs (Extract, Clear, GetValue, etc.), removing ComHolderPreemp, and renaming ComHolderAnyMode to ReleaseHolderAnyMode.
Changes:
- Retargets
ReleaseHolderto aLifetimeHolder<ReleaseHolderTraits<T>>implementation and introducesHolderDetail::HasReleaseMethodfor duck-typedRelease()detection. - Renames / consolidates COM holders (
ComHolderAnyMode→ReleaseHolderAnyMode; removesComHolderPreemp) and migrates call sites toDetach()/Free()patterns. - Refactors a few lifetime/ownership patterns (notably
AppDomain::BindAssemblySpec) to avoid relying on legacy holder APIs.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/vm/wrappers.h | Renames ComHolderAnyModeTraits/alias to ReleaseHolderAnyMode* and removes ComHolderPreemp traits. |
| src/coreclr/vm/weakreferencenative.cpp | Migrates ComHolderPreemp<> usages to ReleaseHolder<>. |
| src/coreclr/vm/stubmgr.cpp | Migrates ComHolderAnyMode<> usages to ReleaseHolderAnyMode<>. |
| src/coreclr/vm/stubhelpers.cpp | Migrates ComHolderAnyMode<> usages to ReleaseHolderAnyMode<>. |
| src/coreclr/vm/stdinterfaces.cpp | Migrates COM holders to ReleaseHolder<> / ReleaseHolderAnyMode<>. |
| src/coreclr/vm/runtimecallablewrapper.cpp | Migrates COM holders and adjusts a CCWHolder lifetime flow to use Detach(). |
| src/coreclr/vm/rejit.cpp | Removes legacy = NULL initialization pattern for ReleaseHolder. |
| src/coreclr/vm/peimagelayout.cpp | Replaces Extract() with Detach() when returning owned layouts. |
| src/coreclr/vm/peimage.cpp | Migrates metadata COM holder to ReleaseHolderAnyMode<>. |
| src/coreclr/vm/peassembly.cpp | Migrates ComHolderPreemp<> to ReleaseHolder<>. |
| src/coreclr/vm/olevariant.cpp | Migrates COM holders to ReleaseHolder<> / ReleaseHolderAnyMode<>. |
| src/coreclr/vm/olecontexthelpers.cpp | Migrates ComHolderPreemp<> to ReleaseHolder<>. |
| src/coreclr/vm/nativeimage.cpp | Replaces legacy holder APIs (IsNull/Extract) with == NULL and Detach(). |
| src/coreclr/vm/marshalnative.cpp | Updates CCWHolder initialization to brace-init and adjusts holder usage. |
| src/coreclr/vm/interoputil.cpp | Call sites migrated to new holder type names. |
| src/coreclr/vm/interopconverter.cpp | Migrates COM holders and replaces legacy holder APIs in a few places. |
| src/coreclr/vm/encee.cpp | Renames holder types in EnC path comments and variables. |
| src/coreclr/vm/eetoprofinterfaceimpl.cpp | Replaces Extract()+NULL patterns with Detach() for ownership transfer. |
| src/coreclr/vm/dllimport.cpp | Updates holder assignment to use operator= instead of Assign. |
| src/coreclr/vm/dispparammarshaler.cpp | Migrates COM holders to ReleaseHolderAnyMode<>. |
| src/coreclr/vm/crossloaderallocatorhash.inl | Updates holder initialization style and uses Detach() for returns. |
| src/coreclr/vm/coreassemblyspec.cpp | Uses Detach() when returning owned binder assembly. |
| src/coreclr/vm/commodule.cpp | Migrates COM holders to ReleaseHolder<> / ReleaseHolderAnyMode<>. |
| src/coreclr/vm/comconnectionpoints.cpp | Migrates ComHolderAnyMode<> to ReleaseHolderAnyMode<>. |
| src/coreclr/vm/comcallablewrapper.cpp | Migrates holders and refactors template-return ownership to use Detach(). |
| src/coreclr/vm/comcache.cpp | Migrates COM holders and replaces Extract() with Detach(). |
| src/coreclr/vm/clrex.cpp | Migrates error-info holder to ReleaseHolderAnyMode<>. |
| src/coreclr/vm/ceeload.cpp | Migrates symbol reader holders to ReleaseHolder<> and modernizes initialization. |
| src/coreclr/vm/assemblynative.cpp | Passes holder directly to tracing (via implicit pointer conversion). |
| src/coreclr/vm/assembly.cpp | Uses Detach() for ownership transfer and brace-init for holders. |
| src/coreclr/vm/appdomain.hpp | Adjusts FindCachedFile signature (removes unused fThrow). |
| src/coreclr/vm/appdomain.cpp | Refactors BindAssemblySpec lifetime management; simplifies FindCachedFile. |
| src/coreclr/md/enc/mdinternalrw.cpp | Fixes QueryInterface call to pass void**. |
| src/coreclr/inc/holder.h | Removes legacy ReleaseHolder wrapper, adds LifetimeHolder-based ReleaseHolder + HasReleaseMethod. |
| src/coreclr/dlls/mscoree/exports.cpp | Uses Detach() to transfer host handle ownership. |
| src/coreclr/debug/ee/debugger.cpp | Migrates ComHolderPreemp<> to ReleaseHolder<>. |
| src/coreclr/debug/daccess/enummem.cpp | Replaces legacy holder APIs (Clear/GetValue) with Free() and direct holder conversions. |
| src/coreclr/debug/daccess/dacdbiimpl.cpp | Removes = nullptr initialization for ReleaseHolder. |
| src/coreclr/debug/daccess/daccess.cpp | Removes = nullptr initialization for ReleaseHolder. |
| src/coreclr/debug/daccess/cdac.h | Replaces Extract() with Detach() in move operations. |
| src/coreclr/debug/createdump/threadinfo.cpp | Replaces Extract() with Detach() when transferring method ownership into a frame. |
| src/coreclr/debug/createdump/createdumpunix.cpp | Updates holder initialization to brace-init. |
| src/coreclr/debug/createdump/crashinfo.cpp | Removes = nullptr initialization for ReleaseHolder. |
| src/coreclr/binder/defaultassemblybinder.cpp | Replaces Extract() with Detach() for binder assembly ownership transfer. |
| src/coreclr/binder/customassemblybinder.cpp | Replaces Extract() with Detach() for binder assembly ownership transfer. |
| src/coreclr/binder/assemblybindercommon.cpp | Replaces Extract() with Detach() for binder assembly ownership transfer. |
| src/coreclr/binder/assembly.cpp | Replaces Extract() with Detach() for assembly-name ownership transfer. |
Copilot's findings
- Files reviewed: 47/47 changed files
- Comments generated: 4
holder.h now includes contract.h (for the MODE_PREEMPTIVE CONTRACTL in ReleaseHolderTraits::Free), which pulled check.inl -> clrhost.h -> holder.h back into itself before Holder/LifetimeHolder were defined. Remove the clrhost.h include from check.inl to break the cycle, and make the two headers that were relying on that transitive path self-sufficient: - inc/sigbuilder.h: include corhdr.h for CorElementType/mdToken. - jit/jitstd/algorithm.h: include <utility> for std::swap used by jitstd::sort. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Open
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Converge the three COM-interface RAII holders (
ReleaseHolder,ComHolderPreemp,ComHolderAnyMode) onto theLifetimeHolder<Traits>pattern.Changes
ReleaseHolderis retargeted toLifetimeHolder<ReleaseHolderTraits<T>>, adoptingComHolderPreemp's preemptive-mode release semantics (the VM default).Free()uses aMODE_PREEMPTIVEcontract gated onENABLE_CONTRACTS_IMPL, so non-VM consumers (utilcode, md, DAC, createdump) fall back to a static-contract annotation.ComHolderPreempis removed;ReleaseHolderreplaces all uses.ComHolderAnyModeis renamed toReleaseHolderAnyMode.static_assertis relaxed fromis_base_of<IUnknown, T>to a duck-typed "Thas aRelease()member" check (holder_detail::HasReleaseMethod), soReleaseHoldercan hold non-IUnknowntypes that exposeRelease().