-
Notifications
You must be signed in to change notification settings - Fork 209
Compiler: Clean up and reduce allocations in declaration intermediate nodes #12024
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
base: main
Are you sure you want to change the base?
Compiler: Clean up and reduce allocations in declaration intermediate nodes #12024
Conversation
visitor.VisitClassDeclaration(this); | ||
} | ||
public void UpdateModifiers(params ImmutableArray<string> modifiers) | ||
=> _modifiers = modifiers.NullToEmpty(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Any caller can specifically pass "default" with no compiler warning.
for (var i = 0; i < typeParameters.Count; i++) | ||
var first = true; | ||
|
||
foreach (var typeParameter in typeParameters) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redacted. Ignore me. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely not! 😄
} | ||
else | ||
{ | ||
writer.Write((string)typeParameter.ParameterName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's definitely not. Good catch!
} | ||
|
||
for (var i = 0; i < suppressWarnings.Count; i++) | ||
for (var i = 0; i < suppressWarnings.Length; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
method.Modifiers.Add("public"); | ||
method.Modifiers.Add("async"); | ||
method.Modifiers.Add("override"); | ||
method.UpdateModifiers("public", "async", "override"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is right, but most of the other places that called the Update* methods were replacing code that did a Clear potentially followed by some Adds. I'm not seeing a Clear in the replaced code here, but I assume it was going to be empty anyways,.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, that's right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public string ClassName { get; set; } | ||
public ImmutableArray<string> Modifiers | ||
{ | ||
get => _modifiers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is field
available here? If so, maybe we could use it for these properties?
|
||
visitor.VisitClassDeclaration(this); | ||
} | ||
public void UpdateModifiers(params ImmutableArray<string> modifiers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the benefit to having these methods over just having a set
instead of an init
on the property? I lean towards just having the setter, even if that means not being able to use the params
, simply to avoid the duplication of calling NullToEmpty
multiple times.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, I was trying to get away from the get; set;
pattern used for intermediate nodes because the state of the data is super unclear. It's very hard to determine what data is or isn't supposed to be set. I'm happy to use field
and do validation and NullToEmpty
in the setters (and the initializer?), but I was hoping to make setters super rare in the intermediate nodes and use "Update" methods for properties that are supposed to be update.
- Enable nullability - Add constructor - Make `IsPrimaryNamespace` property read-only - Remove unnecessary argument null check - Lazily create `Children` collection - General clean up
- Enable nullability - Add constructor - Make `IsPrimaryClass` property read-only - Remove unnecessary argument null check - Lazily create `Children` collection - Change `Modifiers` property to return an `ImmutableArray<string>` rather than an `IList<string>` (backed by a `List<string>`). - Change `Interfaces` property to return an `ImmutableArray<IntermediateToken>` rather than an `IList<IntermediateToken>` (backed by a `List<IntermediateToken>`). - Change `TypeParameters` property to return an `ImmutableArray<TypeParameter>` rather than an `IList<TypeParameter>` (backed by a `List<TypeParameter>`). - General clean up
- Enable nullability - Add constructor - Make properties readonly
Because `CodeRenderingContext` owns the `CodeWriter` instance used for code gen, and the `BuildNamespace` extension method targets `CodeWriter` and also takes a `CodeRenderingContext`, we can change it can target `CodeRenderingContext`.
Because `CodeRenderingContext` owns the `CodeWriter` instance used for code gen, and the `BuildClassDeclaration` extension method targets `CodeWriter` and also takes a `CodeRenderingContext`, we can change it can target `CodeRenderingContext`.
- Enable nullability - Add constructor - Remove unnecessary argument null check - Change `Modifiers` property to return an `ImmutableArray<string>` rather than an `IList<string>` (backed by a `List<string>`). - Change `SupressWarnings` property to return an `ImmutableArray<string>` rather than an `IList<string>` (backed by a `List<string>`). - Make `FieldName`, `FieldType`, and `IsTagHelperField` properties read-only.
- Enable nullability - Add constructor - Remove unnecessary argument null check - Change `Modifiers` property to return an `ImmutableArray<string>` rather than an `IList<string>` (backed by a `List<string>`). - Make `PropertyName`, `ProeprtyType`, and `PropertyExpression` properties read-only.
…ngContext Because `CodeRenderingContext` owns the `CodeWriter` instance used for code gen, and the `WritePropertyDeclaration` and `WriteAutoPropertyDeclaration` extension methods target `CodeWriter` and also take a `CodeRenderingContext`, we can change them can target `CodeRenderingContext`.
…ntext Because `CodeRenderingContext` owns the `CodeWriter` instance used for code gen, and the `BuildLinePragma` and `BuildEnhancedLinePragma` extension methods target `CodeWriter` and also take a `CodeRenderingContext`, we can change them can target `CodeRenderingContext`. In addition, this change changes the type that's returned to readonly ref struct. This requires a bit of adjustment to some of the calling code.
Because `CodeRenderingContext` owns the `CodeWriter` instance used for code gen, and the `WritePadding` extension method targets `CodeWriter` and also takes a `CodeRenderingContext`, we can change it can target `CodeRenderingContext`.
- Enable nullability - Add constructors - Make `IsPrimaryMethod` property read-only - Remove unnecessary argument null check - Lazily create `Children` collection - Change `Modifiers` property to return an `ImmutableArray<string>` rather than an `IList<string>` (backed by a `List<string>`). - Change `Parmeters` property to return an `ImmutableArray<MethodParameter>` rather than an `IList<MethodParameter>` (backed by a `List<MethodParameter>`). - General clean up
- Enable nullability - Add constructors - Make properties read-only
f20d86f
to
7dc5c99
Compare
This pull request cleans up and reduces allocations in declaration-level intermediate nodes:
NamespaceDeclarationIntermediateNode
,ClassDeclarationIntermediateNode
,MethodDeclarationIntermediateNode
,FieldDeclarationIntermediateNode
,PropertyDeclarationIntermediateNode
, and related types. In particular, various collection properties are no longer types asIList<T>
and pre-assigned with aList<T>
instance. Instead, these properties now returnImmutableArray<T>
.Truth be told, this doesn't result in a large reduction in allocations, but this pull request paves the way for future changes.
CI Build: https://dev.azure.com/dnceng/internal/_build/results?buildId=2745495&view=results
Toolset Run: https://dev.azure.com/dnceng/internal/_build/results?buildId=2745496&view=results