From 0471bf995076ff9a241fb4b7d2dcb1a50e36a9e6 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 16 Oct 2024 09:23:19 -0700 Subject: [PATCH] Skip QI and 'IObjectReference' allocation in IDIC fallback --- src/WinRT.Runtime/IWinRTObject.net5.cs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/WinRT.Runtime/IWinRTObject.net5.cs b/src/WinRT.Runtime/IWinRTObject.net5.cs index 1bc813a05..f66a0881c 100644 --- a/src/WinRT.Runtime/IWinRTObject.net5.cs +++ b/src/WinRT.Runtime/IWinRTObject.net5.cs @@ -188,17 +188,21 @@ internal sealed bool IsInterfaceImplementedFallback(RuntimeTypeHandle interfaceT AdditionalTypeData.GetOrAdd(projectIEnum, (_) => new ABI.System.Collections.IEnumerable.AdaptiveFromAbiHelper(type, this)); } - using (objRef) + bool hasMovedObjRefOwnership = false; + + try { var vftblType = helperType.FindVftblType(); + // If there is no nested vftbl type, we want to add the object reference with the IID from the helper type + // to the cache. Rather than doing 'QueryInterface' again with the same IID, on the object reference we + // already have, we can just store that same instance in the cache, and suppress the 'objRef.Dispose()' + // call for it. This avoids that extra call, plus the overhead of allocating a new object reference. + // For all other cases, we dispose the object reference as usual at the end of this scope. if (vftblType is null) { - var qiObjRef = objRef.As(GuidGenerator.GetIID(helperType)); - if (!QueryInterfaceCache.TryAdd(interfaceType, qiObjRef)) - { - qiObjRef.Dispose(); - } + hasMovedObjRefOwnership = QueryInterfaceCache.TryAdd(interfaceType, objRef); + return true; } @@ -230,6 +234,13 @@ static IObjectReference GetObjectReferenceViaVftbl(IObjectReference objRef, Type return true; } + finally + { + if (!hasMovedObjRefOwnership) + { + objRef.Dispose(); + } + } } #if NET8_0_OR_GREATER