Skip to content

Commit

Permalink
ComWrappers test that allocate object can't inline (#85583)
Browse files Browse the repository at this point in the history
* ComWrappers test that allocate object can't inline

There are some JIT stress settings that aggressively
inline functions, regardless of size/complexity. This
inlining can perturb the subtle GC assumptions
inherent in the COM wrappers tests.
  • Loading branch information
AaronRobinsonMSFT committed May 2, 2023
1 parent dc796f7 commit 4772b5d
Showing 1 changed file with 21 additions and 10 deletions.
31 changes: 21 additions & 10 deletions src/tests/Interop/COM/ComWrappers/API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ static void ForceGC()
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void ValidateComInterfaceCreation()
{
Console.WriteLine($"Running {nameof(ValidateComInterfaceCreation)}...");
Expand Down Expand Up @@ -156,6 +157,7 @@ static void ValidateComInterfaceCreation()
Assert.Equal(0, count);
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void ValidateComInterfaceCreationRoundTrip()
{
Console.WriteLine($"Running {nameof(ValidateComInterfaceCreationRoundTrip)}...");
Expand Down Expand Up @@ -212,6 +214,7 @@ static IntPtr CreateObjectAndGetComInterface()
// Just because one use of a COM interface returned from GetOrCreateComInterfaceForObject
// hits zero ref count does not mean future calls to GetOrCreateComInterfaceForObject
// should return an unusable object.
[MethodImpl(MethodImplOptions.NoInlining)]
static void ValidateCreatingAComInterfaceForObjectAfterTheFirstIsFree()
{
Console.WriteLine($"Running {nameof(ValidateCreatingAComInterfaceForObjectAfterTheFirstIsFree)}...");
Expand Down Expand Up @@ -247,6 +250,7 @@ unsafe static void CallSetValue(TestComWrappers wrappers, Test testInstance, int
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void ValidateFallbackQueryInterface()
{
Console.WriteLine($"Running {nameof(ValidateFallbackQueryInterface)}...");
Expand Down Expand Up @@ -300,36 +304,42 @@ static void ValidateCreateObjectCachingScenario()
Assert.NotEqual(trackerObj1, trackerObj3);
}

// Make sure that if one wrapper is GCed, another can be created.
static void ValidateCreateObjectGcBehavior()
// Verify that if a GC nulls the contents of a weak GCHandle but has not yet
// run finializers to remove that GCHandle from the cache, the state of the system is valid.
static void ValidateCreateObjectWeakHandleCacheCleanUp()
{
Console.WriteLine($"Running {nameof(ValidateCreateObjectCachingScenario)}...");
Console.WriteLine($"Running {nameof(ValidateCreateObjectWeakHandleCacheCleanUp)}...");

var cw = new TestComWrappers();

// Get an object from a tracker runtime.
IntPtr trackerObjRaw = MockReferenceTrackerRuntime.CreateTrackerObject();

// Create the first native object wrapper and run the GC.
CreateObject();
CreateObject(cw, trackerObjRaw);

// Only attempt to run the GC, don't wait for the finalizer. We do this
// because of the multiple phase clean-up for ComWrappers caches.
// See weak GC handles in the NativeAOT scenario.
GC.Collect();

// Try to create another wrapper for the same object. The above GC
// may have collected parts of the ComWrapper cache, but this should
// still work.
CreateObject();
// may have collected parts of the ComWrapper cache, but not fully
// cleared the contents of the cache.
CreateObject(cw, trackerObjRaw);
ForceGC();

Marshal.Release(trackerObjRaw);

[MethodImpl(MethodImplOptions.NoInlining)]
void CreateObject()
static void CreateObject(ComWrappers cw, IntPtr trackerObj)
{
var obj = (ITrackerObjectWrapper)cw.GetOrCreateObjectForComInstance(trackerObjRaw, CreateObjectFlags.None);
var obj = (ITrackerObjectWrapper)cw.GetOrCreateObjectForComInstance(trackerObj, CreateObjectFlags.None);
Assert.NotNull(obj);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void ValidateMappingAPIs()
{
Console.WriteLine($"Running {nameof(ValidateMappingAPIs)}...");
Expand Down Expand Up @@ -383,6 +393,7 @@ static void ValidateMappingAPIs()
Marshal.Release(unmanagedObjIUnknown);
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void ValidateWrappersInstanceIsolation()
{
Console.WriteLine($"Running {nameof(ValidateWrappersInstanceIsolation)}...");
Expand Down Expand Up @@ -808,7 +819,7 @@ static int Main()
ValidateCreatingAComInterfaceForObjectAfterTheFirstIsFree();
ValidateFallbackQueryInterface();
ValidateCreateObjectCachingScenario();
ValidateCreateObjectGcBehavior();
ValidateCreateObjectWeakHandleCacheCleanUp();
ValidateMappingAPIs();
ValidateWrappersInstanceIsolation();
ValidatePrecreatedExternalWrapper();
Expand Down

0 comments on commit 4772b5d

Please sign in to comment.