-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
[WIP] Use cached delegate instances for method group conversions #6642
Conversation
Requires thorough EnC, EE and scripting testing and review. |
Thanks for the comments @tmat, I'll fix the generated names. I do aware this needs a lot of testing, but I wanted to submit this early so I can get feedback and see if it get strong objection about how the caching is done. So far I don't see any opinions about that, so I assume it's worth continuing and will add more tests and get back. |
@DiryBoy Sounds good. I'd wait for compiler folks @dotnet/roslyn-compiler to review first before adding more tests to avoid throwaway work. |
@tmat Thanks, I'll wait then. |
return ImmutableArray<Cci.INamespaceTypeDefinition>.Empty; | ||
} | ||
|
||
return StaticCast<Cci.INamespaceTypeDefinition>.From(Compilation.MethodGroupConversionCacheFrameManager.GetAllCreatedFrames()); |
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.
Type casts cannot be used to convert symbols to CCI interfaces, symbols should be translated. Our symbol types claim to implement many different CCI interfaces for efficiency, but it doesn't mean the implementation is correct for all situations, therefore, there is a translation layer that decides if it is appropriate for a certain symbol to implement some interface directly or requires a wrapper, etc.
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.
Thanks for the info, I just copied that method from above, line 383~391
/// <summary> | ||
/// Checks whether a type or a method is constructed with some type that involves the specified generic type parameters. | ||
/// </summary> | ||
internal class TypeParameterUsageChecker : CSharpSymbolVisitor<TypeParams, bool> |
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.
TypeParameterUsageChecker [](start = 19, length = 25)
See TypeSymbolExtensions.ContainsTypeParameter
to see how this could be done in one line.
I am still waiting with baited breath for this to get merged. In the meantime, I think this particular issue could be solved by a Rosslyn code analyzer that provides a code hint automated conversion to the already statically cachable lamda form. |
Here is a brief summary of what we have in this PR at the moment. Delegate instances produced by a method group conversion resolved to a static method (reduced extension methods are excluded) are cached. Delegate instances produced by an object creation expression are not cached. Caching is not performed within static constructors. A delegate instance is cached on a module level when all the following conditions are met:
Otherwise, the delegate instance is cached on the immediate enclosing type level when Otherwise, the delegate instance is cached on the enclosing method level. Tracked TODOs:
Caching on the module level is performed as follows:
Caching on the type level is performed as follows:
Caching on the enclosing method level is performed as follows:
We should consider the following changes to the design/implementation:
|
Thank you @AlekseyTs for the summary and pointers. Question, can we block the compiled binary from loading in the .Net Framework 4.8 and older, or, do we have this kind of mechanism today? If so I think we can continue, as C# spec was changed to allow caching Also noticed local functions can be declared static in the code ensuring no captures in a recent C# version. I think there will be different behaviors from what I observed at the time from the old codebase, and need to re-check. The Roslyn code is evolving fast, a lot of changes in the repo since my last submission. There's no doubt I need some time to go thru the related areas again and rebase the commits properly if to continue on this. So need to be cautious about the blockers ahead. |
The document https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/configure-language-version says,
Can we just enable the caching for C# 9/10 or above? |
This might be ok, but I'd be curious to know what motivates doing this versus just doing the caching the same way for all language versions? |
The main reason is to avoid targeting the old .Net Framework 4.8 or lower as security concerns discussed previously. Another reason is that, I guess, the old spec did not permit caching so that's why the linked issue #5835 said it's being modified to permit this. |
Yes we can do that. In fact I think this is likely what we should be doing but for C# 11 and above. The reasoning is simply compatibility. This will break compatibility for anyone who depended on method group conversions to return new instances. The number of customers that did this is likely to be small but it's also almost certainly greater than zero. When we were first considering this change we hadn't really leaned into using
I want to also say that we are very willing to help with finishing the change. We are very thankful for all the work you did to get this change moving but we understand we paused this change for a long time. We were uncertain if you would want to pick it back up again or not. We are happy to continue helping review your work here or take it over and finish it up (or something in between). Any of these work for us. Again though I do want to thank you for the work you've done thus far. We really appreciate it! |
Thanks @jaredpar for the big Yes, and so yes I'm excited that we are able to pick it back up again! My plan is to use the weekends to do the major things while checking for review feedbacks regularly during weekdays.
I'm happy you are willing to take it over, before that, I do want to make this PR good for review again, at least, then we can decide the directions afterwards, depending on the issues/feedbacks and how fast I could catch up with you guys. |
@pawchen I suggest leaving this PR and the branch as is to make it easier to refer to the existing comments, if need to. And doing the work to "make this PR good for review again" in a different branch (I assume that will involve rebasing on top of current main and squashing commits), then submitting a new PR. |
@AlekseyTs Good idea, thank you for the suggestions. I'll submit a new PR. |
See #5835
This changes C# but not yet VB, vb files are changed to allow compile.