Skip to content

Commit

Permalink
Fix for COM Weakreference test failure under JIT stress. (#79476)
Browse files Browse the repository at this point in the history
* Prevent methods from inlining when relying on life time of their locals.

* refactor local functions.
  • Loading branch information
VSadov committed Dec 10, 2022
1 parent 91af060 commit 9b5b977
Showing 1 changed file with 36 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;

namespace ComWrappersTests
{
using System;
Expand Down Expand Up @@ -132,28 +134,30 @@ private static void ValidateWeakReferenceState(WeakReference<WeakReferenceableWr
Assert.Equal(sourceWrappers.Registration, target.Registration);
}

private static (WeakReference<WeakReferenceableWrapper>, IntPtr) GetWeakReference(TestComWrappers cw)
private static void ValidateNativeWeakReference(TestComWrappers cw)
{
IntPtr objRaw = WeakReferenceNative.CreateWeakReferencableObject();
var obj = (WeakReferenceableWrapper)cw.GetOrCreateObjectForComInstance(objRaw, CreateObjectFlags.None);
var wr = new WeakReference<WeakReferenceableWrapper>(obj);
ValidateWeakReferenceState(wr, expectedIsAlive: true, cw);
GC.KeepAlive(obj);
return (wr, objRaw);
}
[MethodImpl(MethodImplOptions.NoInlining)]
static (WeakReference<WeakReferenceableWrapper>, IntPtr) GetWeakReference(TestComWrappers cw)
{
IntPtr objRaw = WeakReferenceNative.CreateWeakReferencableObject();
var obj = (WeakReferenceableWrapper)cw.GetOrCreateObjectForComInstance(objRaw, CreateObjectFlags.None);
var wr = new WeakReference<WeakReferenceableWrapper>(obj);
ValidateWeakReferenceState(wr, expectedIsAlive: true, cw);
GC.KeepAlive(obj);
return (wr, objRaw);
}

private static IntPtr SetWeakReferenceTarget(WeakReference<WeakReferenceableWrapper> wr, TestComWrappers cw)
{
IntPtr objRaw = WeakReferenceNative.CreateWeakReferencableObject();
var obj = (WeakReferenceableWrapper)cw.GetOrCreateObjectForComInstance(objRaw, CreateObjectFlags.None);
wr.SetTarget(obj);
ValidateWeakReferenceState(wr, expectedIsAlive: true, cw);
GC.KeepAlive(obj);
return objRaw;
}
[MethodImpl(MethodImplOptions.NoInlining)]
static IntPtr SetWeakReferenceTarget(WeakReference<WeakReferenceableWrapper> wr, TestComWrappers cw)
{
IntPtr objRaw = WeakReferenceNative.CreateWeakReferencableObject();
var obj = (WeakReferenceableWrapper)cw.GetOrCreateObjectForComInstance(objRaw, CreateObjectFlags.None);
wr.SetTarget(obj);
ValidateWeakReferenceState(wr, expectedIsAlive: true, cw);
GC.KeepAlive(obj);
return objRaw;
}

private static void ValidateNativeWeakReference(TestComWrappers cw)
{
Console.WriteLine($" -- Validate weak reference creation");
var (weakRef, nativeRef) = GetWeakReference(cw);

Expand Down Expand Up @@ -220,20 +224,20 @@ static void ValidateLocalInstance()

static void ValidateNonComWrappers()
{
Console.WriteLine($"Running {nameof(ValidateNonComWrappers)}...");

(WeakReference, IntPtr) GetWeakReference()
[MethodImpl(MethodImplOptions.NoInlining)]
static (WeakReference, IntPtr) GetWeakReference()
{
IntPtr objRaw = WeakReferenceNative.CreateWeakReferencableObject();
var obj = Marshal.GetObjectForIUnknown(objRaw);
return (new WeakReference(obj), objRaw);
}

bool HasTarget(WeakReference wr)
static bool HasTarget(WeakReference wr)
{
return wr.Target != null;
}

Console.WriteLine($"Running {nameof(ValidateNonComWrappers)}...");
var (weakRef, nativeRef) = GetWeakReference();
GC.Collect();
GC.WaitForPendingFinalizers();
Expand All @@ -254,6 +258,15 @@ bool HasTarget(WeakReference wr)

static void ValidateAggregatedWeakReference()
{
[MethodImpl(MethodImplOptions.NoInlining)]
static (GCHandle handle, WeakReference<DerivedObject>) GetWeakReference()
{
DerivedObject obj = new DerivedObject(TestComWrappers.TrackerSupportInstance);
// We use an explicit weak GC handle here to enable us to validate that we are using "weak" GCHandle
// semantics with the weak reference.
return (GCHandle.Alloc(obj, GCHandleType.Weak), new WeakReference<DerivedObject>(obj));
}

Console.WriteLine("Validate weak reference with aggregation.");
var (handle, weakRef) = GetWeakReference();

Expand All @@ -262,14 +275,6 @@ static void ValidateAggregatedWeakReference()

Assert.Null(handle.Target);
Assert.False(weakRef.TryGetTarget(out _));

static (GCHandle handle, WeakReference<DerivedObject>) GetWeakReference()
{
DerivedObject obj = new DerivedObject(TestComWrappers.TrackerSupportInstance);
// We use an explicit weak GC handle here to enable us to validate that we are using "weak" GCHandle
// semantics with the weak reference.
return (GCHandle.Alloc(obj, GCHandleType.Weak), new WeakReference<DerivedObject>(obj));
}
}

static int Main()
Expand Down

0 comments on commit 9b5b977

Please sign in to comment.