Skip to content

Commit 074c924

Browse files
mandel-macaqueCopilotGitHub Actions Autoformatter
authored
[RGen] Remove all the Nullable<Accessor> boxing that happens in the generator. (#23430)
Similar to #23428 we remove the Nullable boxing of the Accessor struct to reduce the references of the struct from the heap. --------- Co-authored-by: Copilot <[email protected]> Co-authored-by: GitHub Actions Autoformatter <[email protected]>
1 parent 87d4004 commit 074c924

File tree

8 files changed

+60
-34
lines changed

8 files changed

+60
-34
lines changed

src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.Generator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public Accessor (AccessorKind accessorKind,
3535
SymbolAvailability symbolAvailability,
3636
ExportData<ObjCBindings.Property>? exportPropertyData,
3737
ImmutableArray<AttributeCodeChange> attributes,
38-
ImmutableArray<SyntaxToken> modifiers)
38+
ImmutableArray<SyntaxToken> modifiers) : this (StructState.Initialized)
3939
{
4040
Kind = accessorKind;
4141
SymbolAvailability = symbolAvailability;

src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,30 @@
22
// Licensed under the MIT License.
33
using System;
44
using System.Collections.Immutable;
5-
using System.Linq;
65
using System.Runtime.InteropServices;
7-
using System.Text;
86
using Microsoft.CodeAnalysis;
97
using Microsoft.Macios.Generator.Availability;
108

119
namespace Microsoft.Macios.Generator.DataModel;
1210

1311
[StructLayout (LayoutKind.Auto)]
1412
readonly partial struct Accessor : IEquatable<Accessor> {
13+
14+
/// <summary>
15+
/// The initialization state of the struct.
16+
/// </summary>
17+
StructState State { get; init; } = StructState.Default;
18+
19+
/// <summary>
20+
/// Gets the default, uninitialized instance of <see cref="Accessor"/>.
21+
/// </summary>
22+
public static Accessor Default { get; } = new (StructState.Default);
23+
24+
/// <summary>
25+
/// Gets a value indicating whether the instance is the default, uninitialized instance.
26+
/// </summary>
27+
public bool IsNullOrDefault => State == StructState.Default;
28+
1529
/// <summary>
1630
/// The kind of accessor.
1731
/// </summary>
@@ -32,9 +46,21 @@ namespace Microsoft.Macios.Generator.DataModel;
3246
/// </summary>
3347
public ImmutableArray<SyntaxToken> Modifiers { get; }
3448

49+
/// <summary>
50+
/// Initializes a new instance of the <see cref="Accessor"/> struct with a specific state.
51+
/// Used to create the default, uninitialized instance.
52+
/// </summary>
53+
/// <param name="state">The initialization state of the struct.</param>
54+
Accessor (StructState state)
55+
{
56+
State = state;
57+
}
58+
3559
/// <inheritdoc />
3660
public bool Equals (Accessor other)
3761
{
62+
if (State == StructState.Default && other.State == StructState.Default)
63+
return true;
3864
if (Kind != other.Kind)
3965
return false;
4066
if (SymbolAvailability != other.SymbolAvailability)

src/rgen/Microsoft.Macios.Generator/DataModel/Property.Generator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -329,13 +329,13 @@ public Property ToStrongDelegate ()
329329

330330
var getter = GetAccessor (AccessorKind.Getter);
331331
Method? getterMethod = null;
332-
if (getter is not null)
332+
if (!getter.IsNullOrDefault)
333333
getterMethod = new Method (
334334
type: typeInfo.FullyQualifiedName,
335335
name: $"_Get{Name}",
336336
returnType: ReturnType,
337-
symbolAvailability: getter.Value.SymbolAvailability,
338-
exportMethodData: new (getter.Value.GetSelector (this)),
337+
symbolAvailability: getter.SymbolAvailability,
338+
exportMethodData: new (getter.GetSelector (this)),
339339
attributes: [],
340340
modifiers: [Token (SyntaxKind.InternalKeyword), Token (SyntaxKind.StaticKeyword)],
341341
parameters: [thisParameter]) {
@@ -344,7 +344,7 @@ public Property ToStrongDelegate ()
344344

345345
var setter = GetAccessor (AccessorKind.Setter);
346346
Method? setterMethod = null;
347-
if (setter is not null) {
347+
if (!setter.IsNullOrDefault) {
348348
// we need a second parameter for the setter
349349
var valueParameter = new Parameter (1, ReturnType, "value") {
350350
BindAs = BindAs // parameter bindas is the same as the property bindas
@@ -353,8 +353,8 @@ public Property ToStrongDelegate ()
353353
type: typeInfo.FullyQualifiedName,
354354
name: $"_Set{Name}",
355355
returnType: TypeInfo.Void,
356-
symbolAvailability: setter.Value.SymbolAvailability,
357-
exportMethodData: new (setter.Value.GetSelector (this)),
356+
symbolAvailability: setter.SymbolAvailability,
357+
exportMethodData: new (setter.GetSelector (this)),
358358
attributes: [],
359359
modifiers: [Token (SyntaxKind.InternalKeyword), Token (SyntaxKind.StaticKeyword)],
360360
parameters: [thisParameter, valueParameter]);

src/rgen/Microsoft.Macios.Generator/DataModel/Property.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,14 @@ public ImmutableArray<SyntaxToken> Modifiers {
104104

105105
public Parameter ValueParameter { get; private init; }
106106

107-
public Accessor? GetAccessor (AccessorKind accessorKind)
107+
public Accessor GetAccessor (AccessorKind accessorKind)
108108
{
109109
// careful, do not use FirstOrDefault from LINQ because we are using structs!
110110
foreach (var accessor in Accessors) {
111111
if (accessor.Kind == accessorKind)
112112
return accessor;
113113
}
114-
return null;
114+
return Accessor.Default;
115115
}
116116

117117
bool CoreEquals (Property other)

src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Property.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ internal static (string? Getter, string? Setter) GetObjCMessageSendMethods (in P
2626
// export attribute attached
2727
var getter = property.GetAccessor (AccessorKind.Getter);
2828
string? getterMsgSend = null;
29-
if (getter is not null) {
30-
var getterExportData = getter.Value.ExportPropertyData ?? property.ExportPropertyData;
29+
if (!getter.IsNullOrDefault) {
30+
var getterExportData = getter.ExportPropertyData ?? property.ExportPropertyData;
3131
if (getterExportData is not null) {
3232
getterMsgSend = GetObjCMessageSendMethodName (getterExportData.Value, property.BindAs?.Type ?? property.ReturnType, [],
3333
isSuper, isStret);
@@ -36,13 +36,13 @@ internal static (string? Getter, string? Setter) GetObjCMessageSendMethods (in P
3636

3737
var setter = property.GetAccessor (AccessorKind.Setter);
3838
string? setterMsgSend = null;
39-
if (setter is not null) {
39+
if (!setter.IsNullOrDefault) {
4040
// the setter also depends on if we have a bindas attribute or not. If present, the parameter of the
4141
// setter will be that indicated by the bind as attribute
4242
var valueParameter = property.BindAs is null
4343
? property.ValueParameter
4444
: new Parameter (0, property.BindAs.Value.Type, "value");
45-
var setterExportData = setter.Value.ExportPropertyData ?? property.ExportPropertyData;
45+
var setterExportData = setter.ExportPropertyData ?? property.ExportPropertyData;
4646
if (setterExportData is not null) {
4747
setterMsgSend = GetObjCMessageSendMethodName (setterExportData.Value, TypeInfo.Void,
4848
[valueParameter], isSuper, isStret);
@@ -128,13 +128,13 @@ internal static PropertyInvocations GetInvocations (in Property property)
128128
// retrieve the objc_msgSend methods
129129
var (getter, setter) = GetObjCMessageSendMethods (property, isStret: property.ReturnType.NeedsStret);
130130
var (superGetter, superSetter) = GetObjCMessageSendMethods (property, isSuper: true, isStret: property.ReturnType.NeedsStret);
131-
var getterSelector = property.GetAccessor (AccessorKind.Getter)?.GetSelector (property);
131+
var getterSelector = property.GetAccessor (AccessorKind.Getter).GetSelector (property);
132132
var getterInvocations = GetGetterInvocations (property, getterSelector, getter, superGetter);
133133

134134
(ArgumentConversions Argument, ExpressionSyntax Send, ExpressionSyntax SendSuper)? setterInvocations = null;
135135
var setterAccessor = property.GetAccessor (AccessorKind.Setter);
136-
if (setterAccessor is not null) {
137-
var setterSelector = setterAccessor.Value.GetSelector (property);
136+
if (!setterAccessor.IsNullOrDefault) {
137+
var setterSelector = setterAccessor.GetSelector (property);
138138
setterInvocations = GetSetterInvocations (property, setterSelector, setter, superSetter);
139139
}
140140

src/rgen/Microsoft.Macios.Generator/Emitters/ClassEmitter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ void EmitProperties (in BindingContext context, TabbedWriter<StringWriter> class
152152

153153
// we expect to always at least have a getter
154154
var getter = property.GetAccessor (AccessorKind.Getter);
155-
if (getter is null)
155+
if (getter.IsNullOrDefault)
156156
continue;
157157

158158
// add backing variable for the property if it is needed
@@ -168,7 +168,7 @@ void EmitProperties (in BindingContext context, TabbedWriter<StringWriter> class
168168

169169
using (var propertyBlock = classBlock.CreateBlock (property.ToDeclaration ().ToString (), block: true)) {
170170
// be very verbose with the availability, makes the life easier to the dotnet analyzer
171-
propertyBlock.AppendMemberAvailability (getter.Value.SymbolAvailability);
171+
propertyBlock.AppendMemberAvailability (getter.SymbolAvailability);
172172
// if we deal with a delegate, include the attr:
173173
// [return: DelegateProxy (typeof ({staticBridge}))]
174174
if (property.ReturnType.IsDelegate)
@@ -202,12 +202,12 @@ void EmitProperties (in BindingContext context, TabbedWriter<StringWriter> class
202202
}
203203

204204
var setter = property.GetAccessor (AccessorKind.Setter);
205-
if (setter is null || invocations.Setter is null)
205+
if (setter.IsNullOrDefault || invocations.Setter is null)
206206
// we are done with the current property
207207
continue;
208208

209209
propertyBlock.WriteLine (); // add space between getter and setter since we have the attrs
210-
propertyBlock.AppendMemberAvailability (setter.Value.SymbolAvailability);
210+
propertyBlock.AppendMemberAvailability (setter.SymbolAvailability);
211211
// if we deal with a delegate, include the attr:
212212
// [param: BlockProxy (typeof ({nativeInvoker}))]
213213
if (property.ReturnType.IsDelegate)

src/rgen/Microsoft.Macios.Generator/Emitters/ClassEmitterExtensions.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,17 @@ public static void EmitSelectorFields (this IClassEmitter self, in BindingContex
5151
// ignore fields
5252
continue;
5353
var getter = property.GetAccessor (AccessorKind.Getter);
54-
if (getter is not null) {
55-
var selector = getter.Value.GetSelector (property)!;
54+
if (!getter.IsNullOrDefault) {
55+
var selector = getter.GetSelector (property)!;
5656
var selectorName = selector.GetSelectorFieldName ();
5757
if (bindingContext.SelectorNames.TryAdd (selector, selectorName)) {
5858
EmitField (selector, selectorName);
5959
}
6060
}
6161

6262
var setter = property.GetAccessor (AccessorKind.Setter);
63-
if (setter is not null) {
64-
var selector = setter.Value.GetSelector (property)!;
63+
if (!setter.IsNullOrDefault) {
64+
var selector = setter.GetSelector (property)!;
6565
var selectorName = selector.GetSelectorFieldName ();
6666
if (bindingContext.SelectorNames.TryAdd (selector, selectorName)) {
6767
EmitField (selector, selectorName);
@@ -265,7 +265,7 @@ public static void EmitFields (this IClassEmitter self, string className, in Imm
265265
classBlock.WriteLine ();
266266
// a field should always have a getter, if it does not, we do not generate the property
267267
var getter = property.GetAccessor (AccessorKind.Getter);
268-
if (getter is null)
268+
if (getter.IsNullOrDefault)
269269
continue;
270270

271271
// provide a backing variable for the property if and only if we are dealing with a reference type
@@ -289,7 +289,7 @@ public static void EmitFields (this IClassEmitter self, string className, in Imm
289289
var backingField = property.BackingField;
290290

291291
// be very verbose with the availability, makes the life easier to the dotnet analyzer
292-
propertyBlock.AppendMemberAvailability (getter.Value.SymbolAvailability);
292+
propertyBlock.AppendMemberAvailability (getter.SymbolAvailability);
293293
using (var getterBlock = propertyBlock.CreateBlock ("get", block: true)) {
294294
// fields with a reference type have a backing fields, while value types do not
295295
if (property.IsReferenceType) {
@@ -305,12 +305,12 @@ public static void EmitFields (this IClassEmitter self, string className, in Imm
305305
}
306306

307307
var setter = property.GetAccessor (AccessorKind.Setter);
308-
if (setter is null)
308+
if (setter.IsNullOrDefault)
309309
// we are done with the current property
310310
continue;
311311

312312
propertyBlock.WriteLine (); // add space between getter and setter since we have the attrs
313-
propertyBlock.AppendMemberAvailability (setter.Value.SymbolAvailability);
313+
propertyBlock.AppendMemberAvailability (setter.SymbolAvailability);
314314
using (var setterBlock = propertyBlock.CreateBlock ("set", block: true)) {
315315
if (property.IsReferenceType) {
316316
// set the backing field

src/rgen/Microsoft.Macios.Generator/Emitters/StrongDictionaryEmitter.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,26 +44,26 @@ void EmitProperties (in BindingContext context, TabbedWriter<StringWriter> class
4444
foreach (var property in context.Changes.StrongDictionaryProperties.OrderBy (p => p.Name)) {
4545
// make sure that the user did not forget to add the getter
4646
var getter = property.GetAccessor (AccessorKind.Getter);
47-
if (getter is null)
47+
if (getter.IsNullOrDefault)
4848
continue;
4949

5050
classBlock.WriteLine ();
5151
classBlock.AppendMemberAvailability (property.SymbolAvailability);
5252
var (getCall, setCall) = GetStrongDictionaryInvocations (property);
5353
using (var propertyBlock = classBlock.CreateBlock (property.ToDeclaration ().ToString (), block: true)) {
5454

55-
propertyBlock.AppendMemberAvailability (getter.Value.SymbolAvailability);
55+
propertyBlock.AppendMemberAvailability (getter.SymbolAvailability);
5656
using (var getterBlock = propertyBlock.CreateBlock ("get", block: true)) {
5757
getterBlock.WriteLine ($"return {ExpressionStatement (getCall)}");
5858
}
5959

6060
var setter = property.GetAccessor (AccessorKind.Setter);
61-
if (setter is null)
61+
if (setter.IsNullOrDefault)
6262
// we are done with the current property
6363
continue;
6464

6565
propertyBlock.WriteLine (); // add space between getter and setter since we have the attrs
66-
propertyBlock.AppendMemberAvailability (setter.Value.SymbolAvailability);
66+
propertyBlock.AppendMemberAvailability (setter.SymbolAvailability);
6767
using (var setterBlock = propertyBlock.CreateBlock ("set", block: true)) {
6868
setterBlock.WriteLine ($"{ExpressionStatement (setCall)}");
6969
}

0 commit comments

Comments
 (0)