-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Guard overloads for nint/nuint, codegen improvements #3573
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
Conversation
Thanks Sergio0694 for opening a Pull Request! The reviewers will test the PR and highlight if there is any conflict or changes required. If the PR is approved we will proceed to merge the pull request 🙌 |
15f71cb
to
3b5eb17
Compare
#3356 has been merged, so I rebased this PR on top of |
Made a big codegen improvement in 380f6ae as I noticed we weren't really producing the best assembly possible even though we had tried manually inverting the conditional blocks. The previous setup was done mostly just for our internal convenience - this is a bit trickier as we need to check the order of parameters for the various exceptions, but the end result is much, much better 🚀 Small example when just calling ; BEFORE
sub rsp, 40
test rcx, rcx
jne SHORT G_M27046_IG04
mov rdx, 0xD1FFAB1E
mov rdx, gword ptr [rdx]
mov rcx, 0xD1FFAB1E
call Microsoft.Toolkit.Diagnostics.ThrowHelper:ThrowArgumentNullExceptionForIsNotNull(System.String)
G_M27046_IG04:
mov eax, 42
add rsp, 40
ret ; AFTER
sub rsp, 40
test rcx, rcx
je SHORT G_M39878_IG05
mov eax, 42
add rsp, 40
ret
G_M39878_IG05:
mov rdx, 0xD1FFAB1E
mov rdx, gword ptr [rdx]
mov rcx, 0xD1FFAB1E
call Microsoft.Toolkit.Diagnostics.ThrowHelper:ThrowArgumentNullExceptionForIsNotNull2(System.String)
int3 Note how the throw path is now correctly put at the end, the JIT recognizes that ( |
I've restructured the internal architecture for the |
@azchohfi The CI is failing in this PR, but looking at the logs I'm not sure the issue is related to these changes. I'm seeing this:
Any ideas? 😄 |
c03141b
to
467bc3b
Compare
Looking into the CI build error
So the error seems to be when building
public static unsafe void IsBitwiseEqualTo<T>(T value, T target, string name)
where T : unmanaged
{
if (sizeof(T) == 1)
{
if (*(byte*)&value == *(byte*)&target)
{
return;
}
Throw();
}
else if (sizeof(T) == 2)
{
if (*(ushort*)&value == *(ushort*)&target)
{
return;
}
Throw();
}
static void Throw() => throw new Exception();
}
Reverting the changes in 6ace41b at this point, as a temporary workaround to unblock this PR. There shouldn't be a noticeable performance difference anyway in this case, though of course I'd have preferred to keep the revised version 😄 |
This reverts commit 6ace41b to work around a .NET Native compiler bug causing a crash. See more details in CommunityToolkit#3573 (comment).
CI passed! 🎉🎉🎉 |
@Sergio0694 did you e-mail this to the |
/// <summary> | ||
/// Helper methods to efficiently throw exceptions. | ||
/// </summary> | ||
private static partial class ThrowHelper |
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.
Why is this being wrapped in a class now? I think that's the main thing I'm confused about in the PR (and with all the additional new ThrowHelper wraps below). Is this a copy of the other ThrowHelpers or something else?
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.
All these methods have always been wrapped in a class, it's just that before they were inside the public ThrowHelper
class, and internal, while now they're all public and inside a new, private ThrowHelper
class that's nested inside Guard
. There is no behavioral different, it's just a code reorganization. The rationale for this is to make the code compatible (or rather, to make it better) in relation to the source-only Microsoft.Toolkit.Diagnostics
package (#3587). The idea being that if we publish the source-only package and wanted to just copy-paste the Guard
and ThrowHelper
classes into consuming projects, they would've been able to also see all those internal helpers, which would've just cluttered their IntelliSense. With this structure instead all those internal helpers would still be invisible outside of the Guard
class, even if the class was just added as source code directly into your project 🙂
@michael-hawker Yup, sent a full repro to them about an hour ago 😄 |
Hello @michael-hawker! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
This reverts commit f286447 to work around a .NET Native compiler bug causing a crash. See more details in CommunityToolkit/WindowsCommunityToolkit#3573 (comment).
PR Type
What kind of change does this PR introduce?
What is the current behavior?
There are no
nint
/nuint
overloads for the anyGuard
APIs. These types have been introduced with C# 9, so it makes sense to add proper support for them given that #3356 added full support for C# 9 and .NET 5 to these packages.Also there were some codegen bits in
Guard.IsCloseTo
that were not ideal.Additionally, the codegen for the
Guard
APIs didn't leverage compiler support properly.What is the new behavior?
✅ Added new
nint
/nuint
overloads toGuard
APIs🚀 Improved codegen in a number of
Guard.IsCloseTo
overloads🚀 Improved codegen for faulting blocks
PR Checklist
Please check if your PR fulfills the following requirements: