Skip to content
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 explicit null checks for zero-offset struct fields #77641

Merged
merged 3 commits into from
Oct 31, 2022

Conversation

SingleAccretion
Copy link
Contributor

@SingleAccretion SingleAccretion commented Oct 29, 2022

Fixes #77640.

We expect some unavoidable regressions.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Oct 29, 2022
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Oct 29, 2022
@ghost
Copy link

ghost commented Oct 29, 2022

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #77640.

Author: SingleAccretion
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

// This flag is set to enable the "conservative" style of explicit null-check insertion.
// This means that we insert an explicit null check whenever we create byref by adding a
// constant offset to a ref, in a MACK_Addr context (meaning that the byref is not immediately
// dereferenced). The alternative is "aggressive", which would not insert such checks (for
// small offsets); in this plan, we would transfer some null-checking responsibility to
// callee's of methods taking byref parameters. They would have to add explicit null checks
// when creating derived byrefs from argument byrefs by adding constants to argument byrefs, in
// contexts where the resulting derived byref is not immediately dereferenced (or if the offset is too
// large). To make the "aggressive" scheme work, however, we'd also have to add explicit derived-from-null
// checks for byref parameters to "external" methods implemented in C++, and in P/Invoke stubs.
// This is left here to point out how to implement it.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is not correct; ldflda is required by the specification to throw on null addresses, immediately.

@SingleAccretion SingleAccretion marked this pull request as ready for review October 30, 2022 13:57
@SingleAccretion
Copy link
Contributor Author

The diffs are relatively minor, the only large regressions are in MinOpts context from coreclr_tests (on some targets).

This fix will significantly simplify the ADDR(FIELD) => FIELD_ADDR transition.

@dotnet/jit-contrib

@EgorBo
Copy link
Member

EgorBo commented Oct 31, 2022

Reminds me that we used to tolerate this sort of issues and treat pointers to value types as never null.

@EgorBo
Copy link
Member

EgorBo commented Oct 31, 2022

Although the diffs don't look too bad in FullOpts so presumably it's fine?

@jakobbotsch
Copy link
Member

Some of the diffs do look to be in some scary functions:

           3 (20.00 % of base) : 3668.dasm - ConfiguredValueTaskAwaiter[System.__Canon]:get_IsCompleted():bool:this
           3 (20.00 % of base) : 3851.dasm - ConfiguredValueTaskAwaiter[System.__Canon]:GetResult():System.__Canon:this
           3 (20.00 % of base) : 26284.dasm - System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder:SetException(System.Exception):this
           3 (20.00 % of base) : 16608.dasm - System.Runtime.CompilerServices.ValueTaskAwaiter`1[System.__Canon]:get_IsCompleted():bool:this
           3 (20.00 % of base) : 16609.dasm - System.Runtime.CompilerServices.ValueTaskAwaiter`1[System.__Canon]:GetResult():System.__Canon:this
           3 (10.00 % of base) : 16777.dasm - System.Runtime.CompilerServices.AsyncTaskMethodBuilder:AwaitUnsafeOnCompleted[YieldAwaiter,<MultipleSerial>d__23[System.__Canon]](byref,byref):this
           3 (0.53 % of base) : 14294.dasm - System.Collections.Generic.Dictionary`2[uint,System.__Canon]:FindValue(uint):byref:this

We should keep an eye on related benchmarks and/or double check that the diffs in these are not impactful.

@EgorBo
Copy link
Member

EgorBo commented Oct 31, 2022

Some of the diffs do look to be in some scary functions:

           3 (20.00 % of base) : 3668.dasm - ConfiguredValueTaskAwaiter[System.__Canon]:get_IsCompleted():bool:this
           3 (20.00 % of base) : 3851.dasm - ConfiguredValueTaskAwaiter[System.__Canon]:GetResult():System.__Canon:this
           3 (20.00 % of base) : 26284.dasm - System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder:SetException(System.Exception):this
           3 (20.00 % of base) : 16608.dasm - System.Runtime.CompilerServices.ValueTaskAwaiter`1[System.__Canon]:get_IsCompleted():bool:this
           3 (20.00 % of base) : 16609.dasm - System.Runtime.CompilerServices.ValueTaskAwaiter`1[System.__Canon]:GetResult():System.__Canon:this
           3 (10.00 % of base) : 16777.dasm - System.Runtime.CompilerServices.AsyncTaskMethodBuilder:AwaitUnsafeOnCompleted[YieldAwaiter,<MultipleSerial>d__23[System.__Canon]](byref,byref):this
           3 (0.53 % of base) : 14294.dasm - System.Collections.Generic.Dictionary`2[uint,System.__Canon]:FindValue(uint):byref:this

We should keep an eye on related benchmarks and/or double check that the diffs in these are not impactful.

I assume these all are small functions judging by the relative diffs and are inlined in the real world where null-checks might be folded

@SingleAccretion
Copy link
Contributor Author

I assume these all are small functions judging by the relative diffs and are inlined in the real world where null-checks might be folded

That would be my assumption as well. For reference, the large relative diffs mainly come from cases where have a method that immediately tail-calls another (a member function).

@EgorBo EgorBo merged commit 2a42588 into dotnet:main Oct 31, 2022
@SingleAccretion SingleAccretion deleted the Zero-Offset-Fields branch October 31, 2022 20:26
@ghost ghost locked as resolved and limited conversation to collaborators Dec 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The Jit does not add explicit null checks for zero-offset field addresses
3 participants