Skip to content

Commit e5866fe

Browse files
Create an on-stack instance of FindReferenceTargetsCallback. (#116081)
This would remove the transient static value that must be manually managed. It also removes an odd FixedAddressValueType instance.
1 parent 0360335 commit e5866fe

File tree

1 file changed

+17
-8
lines changed

1 file changed

+17
-8
lines changed

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.NativeAot.cs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ namespace System.Runtime.InteropServices
1212
{
1313
internal static partial class TrackerObjectManager
1414
{
15-
[FixedAddressValueType]
16-
internal static readonly unsafe IntPtr s_findReferencesTargetCallback = (IntPtr)Unsafe.AsPointer(in FindReferenceTargetsCallback.Vftbl);
17-
1815
internal static volatile IntPtr s_trackerManager;
1916
internal static volatile bool s_hasTrackingStarted;
2017
internal static volatile bool s_isGlobalPeggingOn = true;
@@ -163,9 +160,8 @@ internal static unsafe void WalkExternalTrackerObjects()
163160
if (nativeObjectWrapper != null &&
164161
nativeObjectWrapper.TrackerObject != IntPtr.Zero)
165162
{
166-
FindReferenceTargetsCallback.s_currentRootObjectHandle = nativeObjectWrapper.ProxyHandle;
167-
int hr = IReferenceTracker.FindTrackerTargets(nativeObjectWrapper.TrackerObject, (IntPtr)Unsafe.AsPointer(in s_findReferencesTargetCallback));
168-
FindReferenceTargetsCallback.s_currentRootObjectHandle = default;
163+
FindReferenceTargetsCallback.Instance callback = new(nativeObjectWrapper.ProxyHandle);
164+
int hr = IReferenceTracker.FindTrackerTargets(nativeObjectWrapper.TrackerObject, (IntPtr)(void*)&callback);
169165
if (hr < 0)
170166
{
171167
walkFailed = true;
@@ -202,7 +198,20 @@ internal static void DetachNonPromotedObjects()
202198
// Callback implementation of IFindReferenceTargetsCallback
203199
internal static unsafe class FindReferenceTargetsCallback
204200
{
205-
internal static GCHandle s_currentRootObjectHandle;
201+
// Define an on-stack compatible COM instance to avoid allocating
202+
// a temporary instance.
203+
[StructLayout(LayoutKind.Sequential)]
204+
internal ref struct Instance
205+
{
206+
private readonly IntPtr _vtable; // First field is IUnknown based vtable.
207+
public GCHandle RootObject;
208+
209+
public Instance(GCHandle handle)
210+
{
211+
_vtable = (IntPtr)Unsafe.AsPointer(in FindReferenceTargetsCallback.Vftbl);
212+
RootObject = handle;
213+
}
214+
}
206215

207216
#pragma warning disable CS3016
208217
[UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])]
@@ -230,7 +239,7 @@ private static unsafe int IFindReferenceTargetsCallback_FoundTrackerTarget(IntPt
230239
return HResults.E_POINTER;
231240
}
232241

233-
object sourceObject = s_currentRootObjectHandle.Target!;
242+
object sourceObject = ((FindReferenceTargetsCallback.Instance*)pThis)->RootObject.Target!;
234243

235244
if (!TryGetObject(referenceTrackerTarget, out object? targetObject))
236245
{

0 commit comments

Comments
 (0)