-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[NativeAOT] macOS/iOS: Emit simple compact unwinding information #88724
Conversation
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsApple platforms can represent certain unwinding sequences more efficiently using a single 32-bit "compact unwinding" code instead of a DWARF EH frame. This format cannot accurately unwind prologs and epilogs. However, we already handle epilogs manually since JIT doesn't generate the DWARF code for it, and prologs could be handled in a similar manner. This is minimum viable prototype that implements the following:
This empty frame prolog accounts for about 30% of the DWARF code / methods in a typical executable, so it has significant impact even without handing the more complex cases.
|
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs
Show resolved
Hide resolved
The general idea looks good to me. The size savings are very nice. The only wrinkle is encoding of the prolog sizes. It looks odd that the prolog sizes are encoded explicitly, and the epilog sizes are inferred from the code. What would it take to infer the prolog size from the compact unwind info or by inspecting the code? |
It should be only needed during GetReturnAddressHijackInfo. It should not be needed during regular unwind. We should never call general unwind in prolog or epilog. |
I originally inferred the prolog size from the instructions but it feels a bit fragile once you start doing complex prologs (not included in the PR). The compact unwind code by itself is not sufficient. It describes the stack layout but not which instructions were used to produce it. Due to various ways how ARM64 code can fold pointer adjustments into single instruction it would be fragile for the general case (again, not issue for this single unwind code that's produced in this PR). If you feel strongly about inferring the prolog size from code I will do it for this simple case and we can extend it later to cover the hard cases. |
We took on this fragility in epilogs, so I think it would be fine to take on it in prologs too and save a bit more size. |
312cadd
to
53117e3
Compare
Done. Let's see if the CI passes... (but it seemed to work locally and crossgen2 compiled the framework just fine) |
/azp run runtime-extra-platforms |
No commit pushedDate could be found for PR 88724 in repo dotnet/runtime |
/azp run runtime-extra-platforms |
Azure Pipelines successfully started running 1 pipeline(s). |
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.
LGTM. @VSadov Could you please take a look as well?
I will take a look. |
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.
LGTM. (just a couple nits). Thanks!!!
Thanks! |
This is causing a lot of intermittent crashes on Linux arm64 . For example: https://helixre8s23ayyeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-89969-merge-fdbcd47e91a0464083/System.Collections.Concurrent.Tests/1/console.07e57ce1.log?helixlogtype=result In checked builds, the crash is typically assertion failure in
|
Thanks for alert, I will check. I must have messed up some condition because it should have had no effect on Linux. |
I see the mistake now, will submit a fix shortly... |
Apple platforms can represent certain unwinding sequences more efficiently using a single 32-bit "compact unwinding" code instead of a DWARF EH frame. This format cannot accurately unwind prologs and epilogs. However, we already handle epilogs manually since JIT doesn't generate the DWARF code for it, and prologs could be handled in a similar manner.
This is minimum viable prototype that implements the following:
This empty frame prolog accounts for about 30% of the DWARF code / methods in a typical executable, so it has significant impact even without handing the more complex cases.
Contributes to #76371, #88292