-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add missing readonly modifiers to GCHandle and DependentHandle #93178
Add missing readonly modifiers to GCHandle and DependentHandle #93178
Conversation
0e536d1
to
be84974
Compare
Storing GCHandles in readonly fields is a pit of failure. Consider: using System.Runtime.InteropServices;
var t = new Test();
t.Dispose();
class Test
{
readonly GCHandle _handle = GCHandle.Alloc(null);
public void Dispose()
{
Console.WriteLine(_handle.IsAllocated);
_handle.Free();
// This prints `true` even though the handle was just freed!
Console.WriteLine(_handle.IsAllocated);
}
} This change does not hurt, but I would avoid storing the GCHandles in |
Tagging subscribers to this area: @dotnet/interop-contrib Issue DetailsThis PR sprinkles a bunch of missing
|
@jkotas I agree that's not a good idea, the real scenario I was thinking about (and the reason why I made this PR) was more about allowing instance methods touching GC handles stored on mutable fields to be marked as readonly without causing defensive copies (eg. if they're just accessing the target of the handle). As a side note I still wish there was some way (or an analyzer perhaps) to spot defensive copies. It's so easy to accidentally invoke a non readonly member on a value that triggers a defensive copy for one reason or another 🥲 |
src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs
Outdated
Show resolved
Hide resolved
src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs
Outdated
Show resolved
Hide resolved
src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs
Show resolved
Hide resolved
src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs
Outdated
Show resolved
Hide resolved
Can you highlight any places where a) this avoids defensive copies, b) those copies involve additional cost, and c) that cost is measurable in any meaningful way? |
src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs
Show resolved
Hide resolved
bdefd85
to
81d7454
Compare
Replying here, I'm responding to a bunch of comments from several threads above as well as emails. Chatted with @AaronRobinsonMSFT offline, and I've updated this PR to only add
I can't, no. This is more of a "conceptual" change (ie. adding |
Thanks. It's not worth making the public API more confusing (making a setter readonly) to make the JIT's life a little bit easier, especially when it's already doing just fine here. |
@jkotas and @stephentoub After the most recent updates, I don't see any obvious concerns with these changes. Do either of you concerns with going forward with these changes? An alternative would be to focus on #94134 as opposed to making changes to |
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.
Looks fine to me.
This PR sprinkles a bunch of missing
readonly
modifiers to APIs ofGCHandle
andDependentHandle
that are not actually modifying instance state. This allows Roslyn to skip some unnecessary defensive copies when invoking any of these APIs over values stored in either readonly fields, or from members marked as readonly (from mutable struct types).