Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
5b3126e
Make delegates immutable
MichalPetryka Mar 3, 2024
64baa1d
Add a comment
MichalPetryka Mar 3, 2024
a489288
Optimize cache checks
MichalPetryka Mar 3, 2024
b0b31bd
Merge branch 'main' into immutable-delegates
MichalPetryka Mar 3, 2024
bc132e4
Fix x86
MichalPetryka Mar 3, 2024
2dce6a8
Fix R2R
MichalPetryka Mar 4, 2024
00fcd02
Update methodcontext.cpp
MichalPetryka Mar 4, 2024
7941123
Fix contract
MichalPetryka Mar 4, 2024
4de2754
Update src/coreclr/vm/object.cpp
MichalPetryka Mar 4, 2024
b9f7f14
Swap fields
MichalPetryka Mar 4, 2024
90c6085
Reorder asserts
MichalPetryka Mar 4, 2024
9509023
Fix contract again
MichalPetryka Mar 4, 2024
557bf4d
GCPROTECT
MichalPetryka Mar 4, 2024
1eab602
Merge branch 'main' into immutable-delegates
MichalPetryka Mar 5, 2024
477a3c5
Merge branch 'main' into immutable-delegates
MichalPetryka Mar 5, 2024
fff595a
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Oct 13, 2024
2c16705
Rework equality checks
MichalPetryka Oct 16, 2024
cbe22f7
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Oct 16, 2024
bb2a509
Fix compile errors
MichalPetryka Oct 16, 2024
3bb047b
Add asserts
MichalPetryka Oct 16, 2024
b957392
Revert some changes, add more caching
MichalPetryka Oct 16, 2024
f3e48e1
Add asserts
MichalPetryka Oct 16, 2024
35e4404
Merge branch 'main' into immutable-delegates
MichalPetryka Oct 17, 2024
8701078
Improve GetHashCode
MichalPetryka Oct 17, 2024
e22a731
Merge branch 'main' into immutable-delegates
MichalPetryka Oct 17, 2024
63cba0a
Fix GetHashCode
MichalPetryka Oct 17, 2024
10964cd
Massage codegen
MichalPetryka Oct 18, 2024
d593b08
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Oct 22, 2024
26b6e61
Apply feedback
MichalPetryka Oct 22, 2024
99e37d6
Overload invocationList for DynamicMethods
MichalPetryka Oct 24, 2024
d9707d2
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka May 10, 2025
b4075c4
Remove newline diff
MichalPetryka May 10, 2025
405309f
Update comdelegate.h
MichalPetryka May 10, 2025
8359913
Merge branch 'main' into immutable-delegates
MichalPetryka Sep 4, 2025
a2185be
Merge branch 'main' into immutable-delegates
MichalPetryka Jan 28, 2026
4d12dc9
Merge branch 'main' into immutable-delegates
MichalPetryka Mar 22, 2026
6caeb42
Update src/coreclr/System.Private.CoreLib/src/System/MulticastDelegat…
MichalPetryka Mar 22, 2026
3492e7d
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Apr 24, 2026
43c2c82
Cleanup
MichalPetryka Apr 24, 2026
179aea1
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jun 3, 2026
ad5645b
Merge branch 'main' into immutable-delegates
MichalPetryka Jun 9, 2026
e0a52e3
Address review
MichalPetryka Jun 10, 2026
80f6ecc
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jun 16, 2026
9c7c07d
Remove CWT, cleanup delegate impl
MichalPetryka Jun 17, 2026
29a5ad4
Remove junk
MichalPetryka Jun 17, 2026
96df463
Refactor delegate marker definitions in comdelegate.cpp
MichalPetryka Jun 17, 2026
efc644e
Revert renames
MichalPetryka Jun 17, 2026
8a91b95
Fix comments
MichalPetryka Jun 17, 2026
94a9b25
Revert missed field
MichalPetryka Jun 17, 2026
f33e751
Optimize invocations
MichalPetryka Jun 17, 2026
20bd567
More cleanup
MichalPetryka Jun 17, 2026
15c9c65
Fix multicast equality
MichalPetryka Jun 17, 2026
561c31b
Merge branch 'main' into immutable-delegates
MichalPetryka Jun 18, 2026
c5b3e0b
Merge branch 'main' into immutable-delegates
MichalPetryka Jun 19, 2026
1d4c034
Merge branch 'main' into immutable-delegates
MichalPetryka Jun 19, 2026
45dc5ed
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jun 19, 2026
68d5505
Address feedback, cleanup
MichalPetryka Jun 19, 2026
262032f
Cleanup more
MichalPetryka Jun 19, 2026
018bc6a
Follow the same pattern as the other places
MichalPetryka Jun 20, 2026
be61178
Fix build
MichalPetryka Jun 20, 2026
9631348
Cleanup native logic
MichalPetryka Jun 20, 2026
5f121f3
Fix build
MichalPetryka Jun 20, 2026
7c103a1
Move methodDesc to invocationCount
MichalPetryka Jun 20, 2026
474c916
Cleanup properties
MichalPetryka Jun 20, 2026
8657011
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jun 20, 2026
c074ec4
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jun 28, 2026
2bafecd
Fixes, cleanup, address feedback
MichalPetryka Jun 28, 2026
cab6bf2
Cleanup merge
MichalPetryka Jun 28, 2026
4d731da
Update comment for virtual delegate method id
MichalPetryka Jun 28, 2026
d99b961
Update comment for virtual delegate handling
MichalPetryka Jun 29, 2026
b2250c7
Review feedback
MichalPetryka Jun 29, 2026
cdda579
Cast NULL to PCODE in comdelegate.cpp
MichalPetryka Jun 29, 2026
8104da0
Fix null pointer comparison in jithelpers.cpp
MichalPetryka Jun 29, 2026
3732a37
Fix method descriptor retrieval for delegate object
MichalPetryka Jun 29, 2026
42253f8
Change delegate invocation count retrieval to extra data
MichalPetryka Jun 29, 2026
527853e
Add HelperObject and ExtraData fields to MockDelegateObjectData
MichalPetryka Jun 29, 2026
137e629
Rename invocationCount to extraData in AddDelegateObject
MichalPetryka Jun 29, 2026
721607b
Refactor GetDelegateInfo test method parameters
MichalPetryka Jun 29, 2026
d2a4831
Fix bad merge
MichalPetryka Jun 29, 2026
c85ad6e
Revert PGO changes
MichalPetryka Jun 29, 2026
58a9d1f
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jul 3, 2026
901adc3
Address feedback, centralise unsafe usage
MichalPetryka Jul 4, 2026
eceec72
Use object
MichalPetryka Jul 4, 2026
c418283
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jul 10, 2026
5ed0119
Address review
MichalPetryka Jul 10, 2026
f21207b
Fix equivalence handling
MichalPetryka Jul 10, 2026
4a237fe
Fix hash code calculation for delegates with type equivalence
MichalPetryka Jul 10, 2026
6f6d24b
Update src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs
MichalPetryka Jul 10, 2026
3ab6fb4
Rename
MichalPetryka Jul 10, 2026
a87c55b
Simplify GetMethodImpl by removing GetMethodImplSlow
MichalPetryka Jul 11, 2026
28de884
Update Delegate.cs
MichalPetryka Jul 11, 2026
9982821
Replace Data.Delegate.UnmanagedMarker with constant
MichalPetryka Jul 11, 2026
d771cf4
Update src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs
MichalPetryka Jul 11, 2026
30bdb4c
Seal Equals and GetHashCode methods in Delegate class
MichalPetryka Jul 11, 2026
7994cb8
Refactor UnmanagedMarker declaration position
MichalPetryka Jul 11, 2026
d2c2fed
Rename variable fRet to pMD in Delegate_GetMethodDesc
MichalPetryka Jul 11, 2026
9448351
Refactor GetMethodDesc for clarity
MichalPetryka Jul 11, 2026
4914734
Update src/coreclr/vm/comdelegate.cpp
MichalPetryka Jul 11, 2026
8db2814
Rename variable for clarity in Delegate.CoreCLR.cs
MichalPetryka Jul 11, 2026
4ea6a95
Merge remote-tracking branch 'upstream/main' into immutable-delegates
MichalPetryka Jul 14, 2026
f8cb0de
Address feedback
MichalPetryka Jul 14, 2026
88a0b0b
Update the kinds table
MichalPetryka Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions docs/design/datacontracts/Object.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ Data descriptors used:
| `SyncTableEntry` | `SyncBlock` | `SyncBlock` corresponding to the entry |
| `ObjectHeader` | `SyncBlockValue` | Sync block value from the object header |
| `SyncBlock` | `HashCode` | Hash code stored in the sync block |
| `Delegate` | `HelperObject` | Invocation list for multicast, MethodInfo otherwise |
| `Delegate` | `Target` | Bound `this` reference for closed delegates |
| `Delegate` | `MethodPtr` | Primary method pointer |
| `Delegate` | `MethodPtrAux` | Auxiliary method pointer |
| `Delegate` | `InvocationCount` | Invocation count (non-zero for multicast/wrapper/unmanaged/special delegates) |
| `Delegate` | `ExtraData` | Invocation count for multicast, UnmanagedMarker for unmanaged, MethodDesc otherwise |
| `ContinuationObject` | `Next` | Pointer to the next continuation in the linked list |
| `ContinuationObject` | `ResumeInfo` | Pointer to the `ResumeInfo` for this suspension point (may be null) |
| `ContinuationObject` | `State` | State index identifying the suspension point within the resumed method |
Expand All @@ -89,6 +90,11 @@ Global variables used:
| `SyncBlockHashCodeMask` | uint32 | Mask for extracting the hash code from the sync block value. |
| `SyncBlockIndexMask` | uint32 | The mask for sync block index field. |

Contract Constants:
| Name | Type | Purpose | Value |
| --- | --- | --- | --- |
| `UnmanagedMarker` | nint | Sentinel value for detecting unmanaged pointer delegates. | `-1` |

Comment thread
MichalPetryka marked this conversation as resolved.
Contracts used:
| Contract Name |
| --- |
Expand Down Expand Up @@ -220,15 +226,25 @@ DelegateInfo GetDelegateInfo(TargetPointer address)
{
Data.Delegate del = new Data.Delegate(target, address);

// Classify the delegate from its invocation count and auxiliary pointer.
// This does not handle open virtual delegates correctly.
DelegateType delegateType = target.ReadNInt(address + /* Delegate::InvocationCount offset */) switch
// Check for multicast and unmanaged first.
bool isMulticast = false;
TargetPointer helperObject = target.ReadPointer(address + /* Delegate::HelperObject offset */);
if (helperObject != TargetPointer.Null)
{
0 => del.MethodPtrAux == TargetCodePointer.Null
? DelegateType.Closed
: DelegateType.Open,
_ => DelegateType.Unknown,
};
IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem;

TargetPointer mt = GetMethodTableAddress(helperObject);
Debug.Assert(mt != TargetPointer.Null);

isMulticast = rts.IsArray(rts.GetTypeHandle(mt), out _);
}

const nint UnmanagedMarker = -1;
DelegateType delegateType = DelegateType.Unknown;
if (!isMulticast && target.ReadNInt(address + /* Delegate::ExtraData offset */) != UnmanagedMarker)
{
delegateType = del.MethodPtrAux == TargetCodePointer.Null ? DelegateType.Closed : DelegateType.Open;
}

// Pick the bound object and primary entry point based on the classification.
// For Closed delegates the target is the bound `this` and MethodPtr is invoked on it.
Expand Down
Loading
Loading