Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce # of allocated objects #1081

Merged
merged 8 commits into from
Jan 21, 2022
15 changes: 15 additions & 0 deletions src/Benchmarks/EventPerf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ public object AddAndInvokeIntEventOnNewEventSource()
return instance;
}

[Benchmark]
public object AddAndInvokeMultipleIntEventsToSameEventSource()
{
ClassWithMarshalingRoutines instance = new ClassWithMarshalingRoutines();
int z;
System.EventHandler<int> s = (object sender, int value) => z = value;
System.EventHandler<int> t = (object sender, int value) => z = value * 2;
System.EventHandler<int> u = (object sender, int value) => z = value * 3;
instance.IntPropertyChanged += s;
instance.IntPropertyChanged += t;
instance.IntPropertyChanged += u;
instance.RaiseIntChanged();
return instance;
}

[Benchmark]
public int InvokeIntEvent()
{
Expand Down
12 changes: 8 additions & 4 deletions src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,23 @@ internal unsafe static bool IsFreeThreaded(IObjectReference objRef)
Marshal.Release(agilePtr);
return true;
}
else if (objRef.TryAs<ABI.WinRT.Interop.IMarshal.Vftbl>(ABI.WinRT.Interop.IMarshal.IID, out var marshalRef) >= 0)
else if (objRef.TryAs(ABI.WinRT.Interop.IMarshal.IID, out var marshalPtr) >= 0)
{
using (marshalRef)
try
{
Guid iid_IUnknown = IUnknownVftbl.IID;
Guid iid_unmarshalClass;
Marshal.ThrowExceptionForHR(marshalRef.Vftbl.GetUnmarshalClass_0(
marshalRef.ThisPtr, &iid_IUnknown, IntPtr.Zero, MSHCTX.InProc, IntPtr.Zero, MSHLFLAGS.Normal, &iid_unmarshalClass));
Marshal.ThrowExceptionForHR((**(ABI.WinRT.Interop.IMarshal.Vftbl**)marshalPtr).GetUnmarshalClass_0(
marshalPtr, &iid_IUnknown, IntPtr.Zero, MSHCTX.InProc, IntPtr.Zero, MSHLFLAGS.Normal, &iid_unmarshalClass));
if (iid_unmarshalClass == ABI.WinRT.Interop.IMarshal.IID_InProcFreeThreadedMarshaler.Value)
{
return true;
}
}
finally
{
Marshal.Release(marshalPtr);
}
}
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/Interop/IContextCallback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public struct Vftbl

public static implicit operator IContextCallback(IObjectReference obj) => (obj != null) ? new IContextCallback(obj) : null;
public static implicit operator IContextCallback(ObjectReference<Vftbl> obj) => (obj != null) ? new IContextCallback(obj) : null;
protected readonly ObjectReference<Vftbl> _obj;
private readonly ObjectReference<Vftbl> _obj;
public IntPtr ThisPtr => _obj.ThisPtr;
public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
public A As<A>() => _obj.AsType<A>();
Expand Down
6 changes: 3 additions & 3 deletions src/WinRT.Runtime/Interop/IMarshal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal sealed class IMarshal

private static readonly string NotImplemented_NativeRoutineNotFound = "A native library routine was not found: {0}.";

internal static Lazy<Guid> IID_InProcFreeThreadedMarshaler = new Lazy<Guid>(Vftbl.GetInProcFreeThreadedMarshalerIID);
internal static readonly Lazy<Guid> IID_InProcFreeThreadedMarshaler = new Lazy<Guid>(Vftbl.GetInProcFreeThreadedMarshalerIID);

[Guid("00000003-0000-0000-c000-000000000046")]
public unsafe struct Vftbl
Expand Down Expand Up @@ -246,12 +246,12 @@ private static int Do_Abi_DisconnectObject_5(IntPtr thisPtr, uint dwReserved)
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);

public static implicit operator IMarshal(IObjectReference obj) => (obj != null) ? new IMarshal(obj) : null;
protected readonly ObjectReference<Vftbl> _obj;
private readonly ObjectReference<Vftbl> _obj;
public IObjectReference ObjRef { get => _obj; }
public IntPtr ThisPtr => _obj.ThisPtr;
public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
public A As<A>() => _obj.AsType<A>();
public IMarshal(IObjectReference obj) : this(obj.As<Vftbl>()) { }
public IMarshal(IObjectReference obj) : this(obj.As<Vftbl>(IID)) { }
internal IMarshal(ObjectReference<Vftbl> obj)
{
_obj = obj;
Expand Down
53 changes: 29 additions & 24 deletions src/WinRT.Runtime/Projections/IDictionary.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ public static unsafe uint get_Size(IObjectReference obj)
var _obj = (ObjectReference<IDictionary<K, V>.Vftbl>)obj;
var ThisPtr = _obj.ThisPtr;
uint __retval = default;
global::WinRT.ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.get_Size_1(ThisPtr, out __retval));
global::WinRT.ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.GetSize_1(ThisPtr, out __retval));
return __retval;
}
}
Expand Down Expand Up @@ -677,7 +677,7 @@ namespace ABI.System.Collections.Generic
interface IDictionary<K, V> : global::System.Collections.Generic.IDictionary<K, V>
{
public static IObjectReference CreateMarshaler(global::System.Collections.Generic.IDictionary<K, V> obj) =>
obj is null ? null : ComWrappersSupport.CreateCCWForObject<Vftbl>(obj, GuidGenerator.GetIID(typeof(IDictionary<K, V>)));
obj is null ? null : ComWrappersSupport.CreateCCWForObject<Vftbl>(obj, PIID);

public static IntPtr GetAbi(IObjectReference objRef) =>
objRef?.ThisPtr ?? IntPtr.Zero;
Expand Down Expand Up @@ -757,60 +757,65 @@ public void _Remove(K key)
}

[Guid("3C2925FE-8519-45C1-AA79-197B6718C1C1")]
public struct Vftbl
public unsafe struct Vftbl
{
internal IInspectable.Vftbl IInspectableVftbl;
public global::System.Delegate Lookup_0;
internal _get_PropertyAsUInt32 get_Size_1;
public global::System.Delegate HasKey_2;
public IDictionary_Delegates.GetView_3 GetView_3;
public global::System.Delegate Lookup_0;
private void* _get_Size_1;
internal delegate* unmanaged[Stdcall]<IntPtr, out uint, int> GetSize_1 { get => (delegate* unmanaged[Stdcall]<IntPtr, out uint, int>)_get_Size_1; set => _get_Size_1 = (void*)value; }
public global::System.Delegate HasKey_2;
private void* _getView_3;
public delegate* unmanaged[Stdcall]<IntPtr, out IntPtr, int> GetView_3 { get => (delegate* unmanaged[Stdcall]<IntPtr, out IntPtr, int>)_getView_3; set => _getView_3 = (void*)value; }
public global::System.Delegate Insert_4;
public global::System.Delegate Remove_5;
public IDictionary_Delegates.Clear_6 Clear_6;
public global::System.Delegate Remove_5;
private void* _clear_6;
public delegate* unmanaged[Stdcall]<IntPtr, int> Clear_6 { get => (delegate* unmanaged[Stdcall]<IntPtr, int>)_clear_6; set => _clear_6 = (void*)value; }
public static Guid PIID = GuidGenerator.CreateIID(typeof(IDictionary<K, V>));
private static readonly Type Lookup_0_Type = Expression.GetDelegateType(new Type[] { typeof(void*), Marshaler<K>.AbiType, Marshaler<V>.AbiType.MakeByRefType(), typeof(int) });
private static readonly Type HasKey_2_Type = Expression.GetDelegateType(new Type[] { typeof(void*), Marshaler<K>.AbiType, typeof(byte).MakeByRefType(), typeof(int) });
private static readonly Type Insert_4_Type = Expression.GetDelegateType(new Type[] { typeof(void*), Marshaler<K>.AbiType, Marshaler<V>.AbiType, typeof(byte).MakeByRefType(), typeof(int) });
private static readonly Type Remove_5_Type = Expression.GetDelegateType(new Type[] { typeof(void*), Marshaler<K>.AbiType, typeof(int) });

internal unsafe Vftbl(IntPtr thisPtr)
internal unsafe Vftbl(IntPtr thisPtr) : this()
{
var vftblPtr = Marshal.PtrToStructure<VftblPtr>(thisPtr);
var vftbl = (IntPtr*)vftblPtr.Vftbl;
IInspectableVftbl = Marshal.PtrToStructure<IInspectable.Vftbl>(vftblPtr.Vftbl);
Lookup_0 = Marshal.GetDelegateForFunctionPointer(vftbl[6], Lookup_0_Type);
get_Size_1 = Marshal.GetDelegateForFunctionPointer<_get_PropertyAsUInt32>(vftbl[7]);
HasKey_2 = Marshal.GetDelegateForFunctionPointer(vftbl[8], HasKey_2_Type);
GetView_3 = Marshal.GetDelegateForFunctionPointer<IDictionary_Delegates.GetView_3>(vftbl[9]);
Lookup_0 = Marshal.GetDelegateForFunctionPointer(vftbl[6], Lookup_0_Type);
GetSize_1 = (delegate* unmanaged[Stdcall]<IntPtr, out uint, int>)vftbl[7];
HasKey_2 = Marshal.GetDelegateForFunctionPointer(vftbl[8], HasKey_2_Type);
GetView_3 = (delegate* unmanaged[Stdcall]<IntPtr, out IntPtr, int>)vftbl[9];
Insert_4 = Marshal.GetDelegateForFunctionPointer(vftbl[10], Insert_4_Type);
Remove_5 = Marshal.GetDelegateForFunctionPointer(vftbl[11], Remove_5_Type);
Clear_6 = Marshal.GetDelegateForFunctionPointer<IDictionary_Delegates.Clear_6>(vftbl[12]);
Remove_5 = Marshal.GetDelegateForFunctionPointer(vftbl[11], Remove_5_Type);
Clear_6 = (delegate* unmanaged[Stdcall]<IntPtr, int>)vftbl[12];
}

private static readonly Vftbl AbiToProjectionVftable;
public static readonly IntPtr AbiToProjectionVftablePtr;
public static readonly IntPtr AbiToProjectionVftablePtr;
private static readonly Delegate[] DelegateCache = new Delegate[3];

static unsafe Vftbl()
{
AbiToProjectionVftable = new Vftbl
{
IInspectableVftbl = global::WinRT.IInspectable.Vftbl.AbiToProjectionVftable,
Lookup_0 = global::System.Delegate.CreateDelegate(Lookup_0_Type, typeof(Vftbl).GetMethod("Do_Abi_Lookup_0", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(Marshaler<K>.AbiType, Marshaler<V>.AbiType)),
get_Size_1 = Do_Abi_get_Size_1,
Lookup_0 = global::System.Delegate.CreateDelegate(Lookup_0_Type, typeof(Vftbl).GetMethod("Do_Abi_Lookup_0", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(Marshaler<K>.AbiType, Marshaler<V>.AbiType)),
_get_Size_1 = (void*)Marshal.GetFunctionPointerForDelegate(DelegateCache[0] = new _get_PropertyAsUInt32(Do_Abi_get_Size_1)),
HasKey_2 = global::System.Delegate.CreateDelegate(HasKey_2_Type, typeof(Vftbl).GetMethod("Do_Abi_HasKey_2", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(Marshaler<K>.AbiType)),
GetView_3 = Do_Abi_GetView_3,
_getView_3 = (void*)Marshal.GetFunctionPointerForDelegate(DelegateCache[1] = new IDictionary_Delegates.GetView_3(Do_Abi_GetView_3)),
Insert_4 = global::System.Delegate.CreateDelegate(Insert_4_Type, typeof(Vftbl).GetMethod("Do_Abi_Insert_4", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(Marshaler<K>.AbiType, Marshaler<V>.AbiType)),
Remove_5 = global::System.Delegate.CreateDelegate(Remove_5_Type, typeof(Vftbl).GetMethod("Do_Abi_Remove_5", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(Marshaler<K>.AbiType)),
Clear_6 = Do_Abi_Clear_6
_clear_6 = (void*)Marshal.GetFunctionPointerForDelegate(DelegateCache[2] = new IDictionary_Delegates.Clear_6(Do_Abi_Clear_6)),
};
var nativeVftbl = (IntPtr*)Marshal.AllocCoTaskMem(Marshal.SizeOf<global::WinRT.IInspectable.Vftbl>() + sizeof(IntPtr) * 7);
Marshal.StructureToPtr(AbiToProjectionVftable.IInspectableVftbl, (IntPtr)nativeVftbl, false);
nativeVftbl[6] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.Lookup_0);
nativeVftbl[7] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.get_Size_1);
nativeVftbl[7] = (IntPtr)AbiToProjectionVftable._get_Size_1;
nativeVftbl[8] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.HasKey_2);
nativeVftbl[9] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.GetView_3);
nativeVftbl[9] = (IntPtr)AbiToProjectionVftable.GetView_3;
nativeVftbl[10] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.Insert_4);
nativeVftbl[11] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.Remove_5);
nativeVftbl[12] = Marshal.GetFunctionPointerForDelegate(AbiToProjectionVftable.Clear_6);
nativeVftbl[12] = (IntPtr)AbiToProjectionVftable.Clear_6;

AbiToProjectionVftablePtr = (IntPtr)nativeVftbl;
}
Expand Down
Loading