From 11fdc52d009565dddb674286647c6042d761d249 Mon Sep 17 00:00:00 2001 From: Marc Zwart Date: Sun, 8 Feb 2026 22:03:20 +0100 Subject: [PATCH] WIP weaktable based function caching --- .../CSharp/CSharpTypeConversionRenderer.cs | 17 ++++++++++++----- TypeShim/MarshallArgumentsTable.cs | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 TypeShim/MarshallArgumentsTable.cs diff --git a/TypeShim.Generator/CSharp/CSharpTypeConversionRenderer.cs b/TypeShim.Generator/CSharp/CSharpTypeConversionRenderer.cs index 681d9873..2c8dbdbe 100644 --- a/TypeShim.Generator/CSharp/CSharpTypeConversionRenderer.cs +++ b/TypeShim.Generator/CSharp/CSharpTypeConversionRenderer.cs @@ -104,9 +104,9 @@ private void RenderInlineTypeDownConversion(InteropTypeInfo typeInfo, string acc { RenderInlineObjectTypeDownConversion(typeInfo, accessorExpressionRenderer); } - else if (typeInfo.IsDelegateType() && typeInfo.ArgumentInfo is DelegateArgumentInfo argumentInfo) // Action/Action/Func + else if (typeInfo.IsDelegateType()) // Action/Action/Func { - RenderInlineDelegateTypeDownConversion(argumentInfo, accessorName, accessorExpressionRenderer); + RenderInlineDelegateTypeDownConversion(typeInfo, accessorName, accessorExpressionRenderer); } else { @@ -226,9 +226,13 @@ private string RenderNullableTaskTypeConversion(InteropTypeInfo targetNullableTa return $"{tcsVarName}?.Task"; } - private void RenderInlineDelegateTypeDownConversion(DelegateArgumentInfo argumentInfo, string accessorName, DeferredExpressionRenderer accessorExpressionRenderer) + private void RenderInlineDelegateTypeDownConversion(InteropTypeInfo typeInfo, string accessorName, DeferredExpressionRenderer accessorExpressionRenderer) { - _ctx.Append('('); + DelegateArgumentInfo argumentInfo = typeInfo.ArgumentInfo ?? throw new InvalidOperationException("Delegate type is missing argumentinfo."); + _ctx.Append("MarshallArgumentsTable.GetOrCreate<").Append(typeInfo.CSharpTypeSyntax).Append(">("); + accessorExpressionRenderer.Render(); + _ctx.Append(", () => ") + .Append('('); for (int i = 0; i < argumentInfo.ParameterTypes.Length; i++) { if (i > 0) _ctx.Append(", "); @@ -257,11 +261,13 @@ private void RenderInlineDelegateTypeDownConversion(DelegateArgumentInfo argumen { invocationExpressionRenderer.Render(); } + _ctx.Append(')'); } private void RenderInlineDelegateTypeUpConversion(InteropTypeInfo typeInfo, string varName, DelegateArgumentInfo argumentInfo) { - _ctx.Append('('); + _ctx.Append("MarshallArgumentsTable.GetOrCreate<").Append(typeInfo.CSharpInteropTypeSyntax).Append(">(").Append(varName).Append(", () => ") + .Append('('); for (int i = 0; i < argumentInfo.ParameterTypes.Length; i++) { if (i > 0) @@ -299,5 +305,6 @@ private void RenderInlineDelegateTypeUpConversion(InteropTypeInfo typeInfo, stri { invocationExpressionRenderer.Render(); } + _ctx.Append(')'); } } \ No newline at end of file diff --git a/TypeShim/MarshallArgumentsTable.cs b/TypeShim/MarshallArgumentsTable.cs new file mode 100644 index 00000000..cc93dd2c --- /dev/null +++ b/TypeShim/MarshallArgumentsTable.cs @@ -0,0 +1,14 @@ +using System.Runtime.CompilerServices; + +namespace TypeShim; + +public static class MarshallArgumentsTable +{ + private static readonly ConditionalWeakTable> _typeTables = new(); + + public static T GetOrCreate(object target, Func factory) where T : class + { + ConditionalWeakTable table = _typeTables.GetValue(typeof(T), _ => new ConditionalWeakTable()); + return (T)table.GetValue(target, _ => factory()!); + } +} \ No newline at end of file