-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
py/emitnative: Optimise native code unwinding jumps. #16608
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
base: master
Are you sure you want to change the base?
Conversation
Code size report:
|
Hrm, the async tests pass for the Unix port on my Arch Linux machine do pass when running Edit: Seems like |
c6b1970
to
86bc821
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #16608 +/- ##
=======================================
Coverage 98.58% 98.58%
=======================================
Files 167 167
Lines 21596 21596
=======================================
Hits 21291 21291
Misses 305 305 ☔ View full report in Codecov by Sentry. |
This commit introduces an optimisation for emitting unwinding jump blocks in native code. Currently the native emitter will emit a jump to the block's unwinding code even though that jump is located right before the unwinding sequence itself. So the unwind code sequence would look like this (as emitted by mpy-cross using "-march=debug"): ... jump(label_0) label(label_0) ... EXIT(0) or: ... jump(label_0) dead_code ... label(label_0) ... EXIT(0) With this change, the native emitter only emits jumps to the exit label (label_0 in the examples above) when unwinding if both the exception stack and the emitter stack are empty, as it means the jump is at the very end of the code block. This fixes issue micropython#16604. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
86bc821
to
3d3ba5e
Compare
So I've marked the PR as draft, as I need to investigate further on what's going on here. |
Whilst the changes proposed here seem to work with production code, I couldn't find a way out to avoid the test failures when compiled with Not sure if it's the tests that expect a specific execution order of the asyncio functions that, if perturbed, makes them fail. In any case, this can be sidestepped as the recompiler already takes care of this. @dpgeorge Is this still worth looking at or can I just close it instead? |
Summary
This PR introduces an optimisation for emitting unwinding jump blocks in native code. Currently the native emitter will emit a jump to the block's unwinding code even though that jump is located right before the unwinding sequence itself. So the unwind code sequence would look like this (as emitted by mpy-cross using "-march=debug"):
or:
With this change, the native emitter only emits jumps to the exit label (label_0 in the examples above) when unwinding if both the exception stack and the emitter stack are empty, as it means the jump is at the very end of the code block.
This fixes issue #16604.
Testing
The full test suite was executed with
make BOARD=VIRT_RV32 RUN_TESTS_EXTRA='--via-mpy --emit native --mpy-cross-flags="-march=rv32imc"' test
on the QEMU/VIRT_RV32 board, and all tests pass. The lack of extra jumps to the unwind label was checked withmpy-cross
emitting code for thedebug
architecture.Trade-offs and Alternatives
This change is dependent on the current native emitter behaviour w.r.t. where to place the unwinding code relative to the unwinding jump. If the assumption of adjacency for the unwinding jump and the unwinding code is invalidated due to other changes to the emitter then this PR will make it generate invalid code.
Ideally this should be turned into a patch that would optimise all jumps regardless their location in the code as long as the label is right before or right after the code sequence in question. However from what I can see it is way more complicated to achieve as the only place where this optimisation can be done is at the lower level of the emitter framework (arch-dependent) and only after the label offsets have been stabilised. Omitting instructions at that point would move label addresses around and thus invalidate computed jumps.