Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork34.2k
gh-144681: Fix JIT trace builder assertion failure when conditional branch jump target coincides with fallthrough target#144742
gh-144681: Fix JIT trace builder assertion failure when conditional branch jump target coincides with fallthrough target#144742cocolato wants to merge 6 commits intopython:mainfrom
Conversation
devdanzin commentedMar 3, 2026
Related:#141797 |
Fidget-Spinner left a comment
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.
Thanks
markshannon left a comment
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.
Thanks for finding the root problem and coming up with a fix. This can be simplified by treatingtarget_instr[1].cache & 1 as the source of truth for branches.
Python/optimizer.c Outdated
| _Py_CODEUNIT *computed_jump_instr = computed_next_instr_without_modifiers + oparg; | ||
| assert(next_instr == computed_next_instr || next_instr == computed_jump_instr); | ||
| int jump_happened = computed_jump_instr == next_instr; | ||
| int jump_happened; |
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.
| intjump_happened; | |
| intjump_happened=target_instr[1].cache&1; |
The direction of the jump is always recorded.
Python/optimizer.c Outdated
| } else { | ||
| jump_happened = computed_jump_instr == next_instr; | ||
| } | ||
| assert(jump_happened == (target_instr[1].cache & 1)); |
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.
| assert(jump_happened==(target_instr[1].cache&1)); | |
| assert(jump_happened? (next_instr==computed_jump_instr) : (next_instr==computed_next_instr)); |
Python/optimizer.c Outdated
| assert(next_instr == computed_next_instr || next_instr == computed_jump_instr); | ||
| int jump_happened = computed_jump_instr == next_instr; | ||
| int jump_happened; | ||
| if (computed_next_instr == computed_jump_instr) { |
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.
Then there is no need to change behavior depending on how long the branch is.
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase And if you don't make the requested changes, you will be poked with soft cushions! |
cocolato commentedMar 9, 2026
Thanks for review! I have made the requested changes; please review again. |
Thanks for making the requested changes! @markshannon,@Fidget-Spinner: please review the changes made to this pull request. |
cocolato commentedMar 9, 2026 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
The failed test appears unrelated to the current PR. It seems to have been introduced here:#145279 |
markshannon commentedMar 9, 2026
Let's see if updating the branch fixes it |
Uh oh!
There was an error while loading.Please reload this page.
When the JIT trace builder translates
POP_JUMP_IF_TRUEinstructions, it determines the branch direction by comparingnext_instr(where execution actually went) againstcomputed_jump_instr(the jump target address). However, when oparg equals 1 and the instruction is followed by NOT_TAKEN, the computed jump target and the computed fallthrough target are the same address:In this minimal reproduction case:
which produces:
the address comparison
computed_jump_instr == next_instris always true regardless of which branch was actually taken, causing the assertionjump_happened == (target_instr[1].cache & 1)failed when the branch was not taken.So we should fall back to the
RECORD_BRANCH_TAKENcache bit (target_instr[1].cache & 1) to determine the branch direction, since address comparison is ambiguous.