@@ -123,6 +123,7 @@ static void ForceGC()
123123 }
124124 }
125125
126+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
126127 static void ValidateComInterfaceCreation ( )
127128 {
128129 Console . WriteLine ( $ "Running { nameof ( ValidateComInterfaceCreation ) } ...") ;
@@ -156,6 +157,7 @@ static void ValidateComInterfaceCreation()
156157 Assert . Equal ( 0 , count ) ;
157158 }
158159
160+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
159161 static void ValidateComInterfaceCreationRoundTrip ( )
160162 {
161163 Console . WriteLine ( $ "Running { nameof ( ValidateComInterfaceCreationRoundTrip ) } ...") ;
@@ -212,6 +214,7 @@ static IntPtr CreateObjectAndGetComInterface()
212214 // Just because one use of a COM interface returned from GetOrCreateComInterfaceForObject
213215 // hits zero ref count does not mean future calls to GetOrCreateComInterfaceForObject
214216 // should return an unusable object.
217+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
215218 static void ValidateCreatingAComInterfaceForObjectAfterTheFirstIsFree ( )
216219 {
217220 Console . WriteLine ( $ "Running { nameof ( ValidateCreatingAComInterfaceForObjectAfterTheFirstIsFree ) } ...") ;
@@ -247,6 +250,7 @@ unsafe static void CallSetValue(TestComWrappers wrappers, Test testInstance, int
247250 }
248251 }
249252
253+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
250254 static void ValidateFallbackQueryInterface ( )
251255 {
252256 Console . WriteLine ( $ "Running { nameof ( ValidateFallbackQueryInterface ) } ...") ;
@@ -300,36 +304,42 @@ static void ValidateCreateObjectCachingScenario()
300304 Assert . NotEqual ( trackerObj1 , trackerObj3 ) ;
301305 }
302306
303- // Make sure that if one wrapper is GCed, another can be created.
304- static void ValidateCreateObjectGcBehavior ( )
307+ // Verify that if a GC nulls the contents of a weak GCHandle but has not yet
308+ // run finializers to remove that GCHandle from the cache, the state of the system is valid.
309+ static void ValidateCreateObjectWeakHandleCacheCleanUp ( )
305310 {
306- Console . WriteLine ( $ "Running { nameof ( ValidateCreateObjectCachingScenario ) } ...") ;
311+ Console . WriteLine ( $ "Running { nameof ( ValidateCreateObjectWeakHandleCacheCleanUp ) } ...") ;
307312
308313 var cw = new TestComWrappers ( ) ;
309314
310315 // Get an object from a tracker runtime.
311316 IntPtr trackerObjRaw = MockReferenceTrackerRuntime . CreateTrackerObject ( ) ;
312317
313318 // Create the first native object wrapper and run the GC.
314- CreateObject ( ) ;
319+ CreateObject ( cw , trackerObjRaw ) ;
320+
321+ // Only attempt to run the GC, don't wait for the finalizer. We do this
322+ // because of the multiple phase clean-up for ComWrappers caches.
323+ // See weak GC handles in the NativeAOT scenario.
315324 GC . Collect ( ) ;
316325
317326 // Try to create another wrapper for the same object. The above GC
318- // may have collected parts of the ComWrapper cache, but this should
319- // still work .
320- CreateObject ( ) ;
327+ // may have collected parts of the ComWrapper cache, but not fully
328+ // cleared the contents of the cache .
329+ CreateObject ( cw , trackerObjRaw ) ;
321330 ForceGC ( ) ;
322331
323332 Marshal . Release ( trackerObjRaw ) ;
324333
325334 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
326- void CreateObject ( )
335+ static void CreateObject ( ComWrappers cw , IntPtr trackerObj )
327336 {
328- var obj = ( ITrackerObjectWrapper ) cw . GetOrCreateObjectForComInstance ( trackerObjRaw , CreateObjectFlags . None ) ;
337+ var obj = ( ITrackerObjectWrapper ) cw . GetOrCreateObjectForComInstance ( trackerObj , CreateObjectFlags . None ) ;
329338 Assert . NotNull ( obj ) ;
330339 }
331340 }
332341
342+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
333343 static void ValidateMappingAPIs ( )
334344 {
335345 Console . WriteLine ( $ "Running { nameof ( ValidateMappingAPIs ) } ...") ;
@@ -383,6 +393,7 @@ static void ValidateMappingAPIs()
383393 Marshal . Release ( unmanagedObjIUnknown ) ;
384394 }
385395
396+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
386397 static void ValidateWrappersInstanceIsolation ( )
387398 {
388399 Console . WriteLine ( $ "Running { nameof ( ValidateWrappersInstanceIsolation ) } ...") ;
@@ -808,7 +819,7 @@ static int Main()
808819 ValidateCreatingAComInterfaceForObjectAfterTheFirstIsFree ( ) ;
809820 ValidateFallbackQueryInterface ( ) ;
810821 ValidateCreateObjectCachingScenario ( ) ;
811- ValidateCreateObjectGcBehavior ( ) ;
822+ ValidateCreateObjectWeakHandleCacheCleanUp ( ) ;
812823 ValidateMappingAPIs ( ) ;
813824 ValidateWrappersInstanceIsolation ( ) ;
814825 ValidatePrecreatedExternalWrapper ( ) ;
0 commit comments