-
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
JIT: Assertion failed 'endOffset > startOffset' during 'Emit GC+EH tables' #106379
Comments
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
On ARM platforms, the emitter splits up exceptionally large methods and reports EH info in 512KB chunks. Under rare stress circumstances (0.5% odds of firing when Since having a zero-sized fragment will trigger asserts, I suppose it is preferable to not respect the desired chunk size, and skip the last split if it will create a zero-sized fragment. Doing so doesn't have correctness consequences under stress modes, as far as I know. But under normal circumstances, if we have a candidate chunk that is exactly 512KB and we decide to not split it to avoid creating a zero-sized fragment, we will probably break ISA invariants around EH data. This seems like a highly unlikely scenario (TODO comments suggest this chunk limit is 1MB on ARM64, making it even more unlikely there), and fixing it would probably require padding out the last chunk to not be zero-sized; I don't think we need to fix this yet. Since this only impacts stress modes for the time being, and the odds of this specific stress mode firing are quite low, I don't think we need to backport a fix for this, but I'm happy to do so if I get pushback. |
I was finally able to repro this myself and investigate. The case here is quite weird: there is a loop within a 'try' block in a funclet that includes a nested 'finally' handler funclet that physically precedes the loop's "main" funclet. The alignment code considers aligning this loop, so it inserts "align" pseudo-instructions before the first block of the loop, which happens to be the first funclet (which is a single-block 'finally' funclet). Thus, the alignment instructions are "between" the end of the main body and the beginning of the funclet region. The IR when placing the 'align' instructions is:
during codegen, 16 bytes of 'align' instructions are inserted after the main function, in a new IG. Later, loop alignment decides to not align the loop, so it zeros out these alignment instructions, leaving a zero-sized IG. It seems unlikely there are any scenarios besides the alignment case described above that will create a zero-sized IG. It does seem like it would be possible to hit this in real code, though of course it would be extremely rare. |
@kunalspathak The above comment describes a situation that surprised me somewhat, that arises from loops now being able to contain multiple different funclets, that are laid out in non-contiguous "arbitrary" fashion compared to the loop itself. Do you think the alignment code will "do the right thing" in all the possible cases? E.g., what if there are multiple loops meriting alignment, each containing different funclets; inserting one alignment pad might conflict with and/or prevent the other loop's alignment pad. |
Hit by Antigen on Linux arm64:
cc @dotnet/jit-contrib
The text was updated successfully, but these errors were encountered: