Skip to content

Commit 17cc487

Browse files
authored
Reduce allocations (#1620)
* Reduce allocations when constructing syntax nodes * Qualify `Marshal` name * Revert collection expression usage to avoid style warning
1 parent 3686850 commit 17cc487

20 files changed

Lines changed: 851 additions & 915 deletions

src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs
2020
TypeSyntaxAndMarshaling element = this.ElementType.ToTypeSyntax(inputs, forElement, customAttributes);
2121
if (inputs.AllowMarshaling || inputs.IsField)
2222
{
23-
ArrayTypeSyntax arrayType = ArrayType(element.Type, SingletonList(ArrayRankSpecifier().AddSizes(this.Shape.Sizes.Select(size => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size))).ToArray<ExpressionSyntax>())));
23+
ArrayTypeSyntax arrayType = ArrayType(element.Type, [ArrayRankSpecifier([.. this.Shape.Sizes.Select(size => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size)))])]);
2424
MarshalAsAttribute? marshalAs = element.MarshalAsAttribute is object ? new MarshalAsAttribute(UnmanagedType.LPArray) { ArraySubType = element.MarshalAsAttribute.Value } : null;
2525
return new TypeSyntaxAndMarshaling(arrayType, marshalAs, element.NativeArrayInfo);
2626
}

src/Microsoft.Windows.CsWin32/FastSyntaxFactory.cs

Lines changed: 39 additions & 71 deletions
Large diffs are not rendered by default.

src/Microsoft.Windows.CsWin32/Generator.Com.cs

Lines changed: 137 additions & 154 deletions
Large diffs are not rendered by default.

src/Microsoft.Windows.CsWin32/Generator.Constant.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ ReadOnlyMemory<char> TrimCurlyBraces(ReadOnlyMemory<char> arg)
227227
i++;
228228
}
229229

230-
return ObjectCreationExpression(targetType).AddArgumentListArguments(argExpressions);
230+
return ObjectCreationExpression(targetType, [.. argExpressions]);
231231
}
232232
}
233233

@@ -259,7 +259,7 @@ ReadOnlyMemory<char> TrimCurlyBraces(ReadOnlyMemory<char> arg)
259259

260260
return ObjectCreationExpression(targetType)
261261
.WithArgumentList(null)
262-
.WithInitializer(InitializerExpression(SyntaxKind.ObjectInitializerExpression, SeparatedList<ExpressionSyntax>()).AddExpressions(fieldAssignmentExpressions));
262+
.WithInitializer(InitializerExpression(SyntaxKind.ObjectInitializerExpression).AddExpressions(fieldAssignmentExpressions));
263263
}
264264

265265
private ExpressionSyntax CreateConstant(ReadOnlyMemory<char> argsAsString, TypeHandleInfo targetType, out bool unsafeRequired)
@@ -312,8 +312,7 @@ private ExpressionSyntax CreateByteArrayConstant(ReadOnlyMemory<char> argsAsStri
312312
TypeSyntax byteTypeSyntax = PredefinedType(Token(SyntaxKind.ByteKeyword));
313313
return CastExpression(
314314
MakeReadOnlySpanOfT(byteTypeSyntax),
315-
ArrayCreationExpression(ArrayType(byteTypeSyntax).AddRankSpecifiers(ArrayRankSpecifier())).WithInitializer(InitializerExpression(SyntaxKind.ArrayInitializerExpression, SeparatedList<ExpressionSyntax>())
316-
.AddExpressions(args.Select(b => ToExpressionSyntax(PrimitiveTypeCode.Byte, b)).ToArray())));
315+
ArrayCreationExpression(ArrayType(byteTypeSyntax, [ArrayRankSpecifier()]), InitializerExpression(SyntaxKind.ArrayInitializerExpression, [.. args.Select(b => ToExpressionSyntax(PrimitiveTypeCode.Byte, b))])));
317316
}
318317

319318
private ExpressionSyntax CreateGuidConstant(List<ReadOnlyMemory<char>> guidArgs)
@@ -338,7 +337,7 @@ private ExpressionSyntax CreateGuidConstant(List<ReadOnlyMemory<char>> guidArgs)
338337
Literal(byte.Parse(guidArgs[10].ToString(), CultureInfo.InvariantCulture)),
339338
};
340339

341-
return ObjectCreationExpression(GuidTypeSyntax).AddArgumentListArguments(ctorArgs.Select(t => Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, t))).ToArray());
340+
return ObjectCreationExpression(GuidTypeSyntax, [.. ctorArgs.Select(t => Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, t)))]);
342341
}
343342

344343
private ExpressionSyntax CreateConstant(CustomAttribute constantAttribute, TypeHandleInfo targetType, out bool unsafeRequired)
@@ -389,7 +388,7 @@ private FieldDeclarationSyntax DeclareConstant(FieldDefinition fieldDef)
389388
}
390389
}
391390

392-
SyntaxTokenList modifiers = TokenList(TokenWithSpace(this.Visibility));
391+
SyntaxTokenList modifiers = [TokenWithSpace(this.Visibility)];
393392
if (this.IsTypeDefStruct(fieldTypeInfo) || value is ObjectCreationExpressionSyntax)
394393
{
395394
modifiers = modifiers.Add(TokenWithSpace(SyntaxKind.StaticKeyword)).Add(TokenWithSpace(SyntaxKind.ReadOnlyKeyword));
@@ -404,9 +403,7 @@ private FieldDeclarationSyntax DeclareConstant(FieldDefinition fieldDef)
404403
modifiers = modifiers.Add(TokenWithSpace(SyntaxKind.UnsafeKeyword));
405404
}
406405

407-
FieldDeclarationSyntax? result = FieldDeclaration(VariableDeclaration(fieldType.Type).AddVariables(
408-
VariableDeclarator(Identifier(name)).WithInitializer(EqualsValueClause(value))))
409-
.WithModifiers(modifiers);
406+
FieldDeclarationSyntax? result = FieldDeclaration(modifiers, VariableDeclaration(fieldType.Type, [VariableDeclarator(Identifier(name), EqualsValueClause(value))]));
410407
result = fieldType.AddMarshalAs(result);
411408
result = this.AddApiDocumentation(result.Declaration.Variables[0].Identifier.ValueText, result);
412409

@@ -423,8 +420,7 @@ private FieldDeclarationSyntax DeclareConstant(FieldDefinition fieldDef)
423420

424421
private ClassDeclarationSyntax DeclareConstantDefiningClass()
425422
{
426-
return ClassDeclaration(this.methodsAndConstantsClassName.Identifier)
427-
.AddMembers(this.committedCode.TopLevelFields.ToArray())
428-
.WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)));
423+
return ClassDeclaration(this.methodsAndConstantsClassName.Identifier, [.. this.committedCode.TopLevelFields])
424+
.WithModifiers([TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.PartialKeyword)]);
429425
}
430426
}

src/Microsoft.Windows.CsWin32/Generator.CustomMarshaller.cs

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,8 @@ internal string RequestCustomEnumMarshaller(string qualifiedEnumTypeName, Unmana
6767
// }
6868
MethodDeclarationSyntax convertToManagedMethod = MethodDeclaration(enumTypeSyntax, Identifier("ConvertToManaged"))
6969
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.UnsafeKeyword))
70-
.AddParameterListParameters(Parameter(Identifier("unmanaged")).WithType(unmanagedTypeSyntax.WithTrailingTrivia(Space)))
71-
.WithBody(Block().AddStatements(
72-
ReturnStatement(UncheckedExpression(CastExpression(enumTypeSyntax, IdentifierName("unmanaged"))))));
70+
.AddParameterListParameters(Parameter(unmanagedTypeSyntax.WithTrailingTrivia(Space), Identifier("unmanaged")))
71+
.WithBody(Block(ReturnStatement(UncheckedExpression(CastExpression(enumTypeSyntax, IdentifierName("unmanaged"))))));
7372

7473
// Create ConvertToUnmanaged method
7574
// public static uint ConvertToUnmanaged(Enum managed)
@@ -78,24 +77,22 @@ internal string RequestCustomEnumMarshaller(string qualifiedEnumTypeName, Unmana
7877
// }
7978
MethodDeclarationSyntax convertToUnmanagedMethod = MethodDeclaration(unmanagedTypeSyntax, Identifier("ConvertToUnmanaged"))
8079
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword))
81-
.AddParameterListParameters(Parameter(Identifier("managed")).WithType(enumTypeSyntax.WithTrailingTrivia(Space)))
82-
.WithBody(Block().AddStatements(
83-
ReturnStatement(UncheckedExpression(CastExpression(unmanagedTypeSyntax, IdentifierName("managed"))))));
80+
.AddParameterListParameters(Parameter(enumTypeSyntax.WithTrailingTrivia(Space), Identifier("managed")))
81+
.WithBody(Block(ReturnStatement(UncheckedExpression(CastExpression(unmanagedTypeSyntax, IdentifierName("managed"))))));
8482

8583
// Create Free method
8684
// public static void Free(uint unmanaged)
8785
// {
8886
// }
8987
MethodDeclarationSyntax freeMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Free"))
9088
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword))
91-
.AddParameterListParameters(Parameter(Identifier("unmanaged")).WithType(unmanagedTypeSyntax.WithTrailingTrivia(Space)))
89+
.AddParameterListParameters(Parameter(unmanagedTypeSyntax.WithTrailingTrivia(Space), Identifier("unmanaged")))
9290
.WithBody(Block()); // Empty body
9391

9492
// Create the class declaration
95-
ClassDeclarationSyntax marshallerClass = ClassDeclaration(Identifier(customTypeMarshallerName))
93+
ClassDeclarationSyntax marshallerClass = ClassDeclaration(Identifier(customTypeMarshallerName), [convertToManagedMethod, convertToUnmanagedMethod, freeMethod])
9694
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword))
97-
.AddAttributeLists(customMarshallerAttributes.Select(attr => AttributeList().AddAttributes(attr)).ToArray())
98-
.AddMembers(convertToManagedMethod, convertToUnmanagedMethod, freeMethod);
95+
.AddAttributeLists(customMarshallerAttributes.Select(attr => AttributeList(attr)).ToArray());
9996

10097
marshallerClass = marshallerClass.WithAdditionalAnnotations(new SyntaxAnnotation(NamespaceContainerAnnotation, shortNamespace));
10198

@@ -140,20 +137,18 @@ internal string RequestCustomTypeDefMarshaller(string fullyQualifiedTypeName, Ty
140137
// public static unsafe void* ConvertToUnmanaged(HWND managed) => managed.Value;
141138
MethodDeclarationSyntax toUnmanaged = MethodDeclaration(unmanagedTypeSyntax, Identifier("ConvertToUnmanaged"))
142139
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.UnsafeKeyword))
143-
.AddParameterListParameters(Parameter(Identifier("managed")).WithType(typedefTypeSyntax.WithTrailingTrivia(Space)))
140+
.AddParameterListParameters(Parameter(typedefTypeSyntax.WithTrailingTrivia(Space), Identifier("managed")))
144141
.WithBody(Block(ReturnStatement(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("managed"), IdentifierName("Value")))));
145142

146143
// public static unsafe HWND ConvertToManaged(void* unmanaged) => new(unmanaged);
147144
MethodDeclarationSyntax toManaged = MethodDeclaration(typedefTypeSyntax, Identifier("ConvertToManaged"))
148145
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.UnsafeKeyword))
149-
.AddParameterListParameters(Parameter(Identifier("unmanaged")).WithType(unmanagedTypeSyntax.WithTrailingTrivia(Space)))
150-
.WithBody(Block(ReturnStatement(ObjectCreationExpression(typedefTypeSyntax)
151-
.WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(IdentifierName("unmanaged"))))))));
146+
.AddParameterListParameters(Parameter(unmanagedTypeSyntax.WithTrailingTrivia(Space), Identifier("unmanaged")))
147+
.WithBody(Block(ReturnStatement(ObjectCreationExpression(typedefTypeSyntax, [Argument(IdentifierName("unmanaged"))]))));
152148

153-
ClassDeclarationSyntax marshallerClass = ClassDeclaration(Identifier(customTypeMarshallerName))
149+
ClassDeclarationSyntax marshallerClass = ClassDeclaration(Identifier(customTypeMarshallerName), [toUnmanaged, toManaged])
154150
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword))
155-
.AddAttributeLists(AttributeList().AddAttributes(attribute))
156-
.AddMembers(toUnmanaged, toManaged)
151+
.AddAttributeLists(AttributeList(attribute))
157152
.WithAdditionalAnnotations(new SyntaxAnnotation(NamespaceContainerAnnotation, shortNamespace));
158153

159154
string qualifiedName = $"global::{this.Namespace}.{shortNamespace}.{customTypeMarshallerName}";
@@ -215,15 +210,14 @@ internal string RequestCustomWinRTMarshaller(string qualifiedWinRTTypeName)
215210
// }
216211
MethodDeclarationSyntax convertToManagedMethod = MethodDeclaration(winrtTypeSyntax, Identifier("ConvertToManaged"))
217212
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.UnsafeKeyword))
218-
.AddParameterListParameters(Parameter(Identifier("unmanaged")).WithType(unmanagedTypeSyntax.WithTrailingTrivia(Space)))
219-
.WithBody(Block().AddStatements(
213+
.AddParameterListParameters(Parameter(unmanagedTypeSyntax.WithTrailingTrivia(Space), Identifier("unmanaged")))
214+
.WithBody(Block(
220215
ReturnStatement(InvocationExpression(
221216
MemberAccessExpression(
222217
SyntaxKind.SimpleMemberAccessExpression,
223-
GenericName("global::WinRT.MarshalInterface")
224-
.AddTypeArgumentListArguments(winrtTypeSyntax),
218+
GenericName("global::WinRT.MarshalInterface", [winrtTypeSyntax]),
225219
IdentifierName("FromAbi")),
226-
ArgumentList().AddArguments(Argument(IdentifierName("unmanaged")))))));
220+
[Argument(IdentifierName("unmanaged"))]))));
227221

228222
// Create ConvertToUnmanaged method
229223
// public static nint ConvertToUnmanaged(T managed)
@@ -232,15 +226,14 @@ internal string RequestCustomWinRTMarshaller(string qualifiedWinRTTypeName)
232226
// }
233227
MethodDeclarationSyntax convertToUnmanagedMethod = MethodDeclaration(unmanagedTypeSyntax, Identifier("ConvertToUnmanaged"))
234228
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword))
235-
.AddParameterListParameters(Parameter(Identifier("managed")).WithType(winrtTypeSyntax.WithTrailingTrivia(Space)))
236-
.WithBody(Block().AddStatements(
229+
.AddParameterListParameters(Parameter(winrtTypeSyntax.WithTrailingTrivia(Space), Identifier("managed")))
230+
.WithBody(Block(
237231
ReturnStatement(InvocationExpression(
238232
MemberAccessExpression(
239233
SyntaxKind.SimpleMemberAccessExpression,
240-
GenericName("global::WinRT.MarshalInterface")
241-
.AddTypeArgumentListArguments(winrtTypeSyntax),
234+
GenericName("global::WinRT.MarshalInterface", [winrtTypeSyntax]),
242235
IdentifierName("FromManaged")),
243-
ArgumentList().AddArguments(Argument(IdentifierName("managed")))))));
236+
[Argument(IdentifierName("managed"))]))));
244237

245238
// Create Free method
246239
// public static void Free(nint unmanaged)
@@ -249,21 +242,19 @@ internal string RequestCustomWinRTMarshaller(string qualifiedWinRTTypeName)
249242
// }
250243
MethodDeclarationSyntax freeMethod = MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier("Free"))
251244
.AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword))
252-
.AddParameterListParameters(Parameter(Identifier("unmanaged")).WithType(unmanagedTypeSyntax.WithTrailingTrivia(Space)))
253-
.WithBody(Block().AddStatements(
245+
.AddParameterListParameters(Parameter(unmanagedTypeSyntax.WithTrailingTrivia(Space), Identifier("unmanaged")))
246+
.WithBody(Block(
254247
ExpressionStatement(InvocationExpression(
255248
MemberAccessExpression(
256249
SyntaxKind.SimpleMemberAccessExpression,
257-
GenericName("global::WinRT.MarshalInterface")
258-
.AddTypeArgumentListArguments(winrtTypeSyntax),
250+
GenericName("global::WinRT.MarshalInterface", [winrtTypeSyntax]),
259251
IdentifierName("DisposeAbi")),
260-
ArgumentList().AddArguments(Argument(IdentifierName("unmanaged")))))));
252+
[Argument(IdentifierName("unmanaged"))]))));
261253

262254
// Create the class declaration
263-
ClassDeclarationSyntax marshallerClass = ClassDeclaration(Identifier(customTypeMarshallerName))
255+
ClassDeclarationSyntax marshallerClass = ClassDeclaration(Identifier(customTypeMarshallerName), [convertToManagedMethod, convertToUnmanagedMethod, freeMethod])
264256
.AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.StaticKeyword))
265-
.AddAttributeLists(customMarshallerAttributes.Select(attr => AttributeList().AddAttributes(attr)).ToArray())
266-
.AddMembers(convertToManagedMethod, convertToUnmanagedMethod, freeMethod);
257+
.AddAttributeLists(customMarshallerAttributes.Select(attr => AttributeList(attr)).ToArray());
267258

268259
marshallerClass = marshallerClass.WithAdditionalAnnotations(new SyntaxAnnotation(NamespaceContainerAnnotation, marshallerNamespace));
269260

0 commit comments

Comments
 (0)