Repository navigation
Do not follow END_ASYNC_FOR's monitoring-only jump when computing stack size (Python 3.14) - #214
Merged
MatthieuDartiailh merged 2 commits intoOct 2, 2026
Conversation
yuri12344
pushed a commit
to yuri12344/bytecode
that referenced
this pull request
Oct 2, 2026
…ck size On Python 3.14 END_ASYNC_FOR has a jump argument that only provides the source offset for sys.monitoring: the interpreter never takes it (JUMPBY(0) in Python/bytecodes.c) and CPython's calculate_stackdepth skips this edge. Following it made the stack-size computation enter the loop's SEND/END_SEND block with the enclosing TryBegin still open, which raised an AssertionError for functions with several async for loops containing try blocks.
yuri12344
force-pushed
the
fix-end-async-for-stacksize-py314
branch
from
October 2, 2026 10:46
21b0ddd to
e5564e0
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #214 +/- ##
=======================================
Coverage 95.57% 95.57%
=======================================
Files 7 7
Lines 2147 2148 +1
Branches 461 461
=======================================
+ Hits 2052 2053 +1
Misses 53 53
Partials 42 42 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
MatthieuDartiailh
approved these changes
Oct 2, 2026
MatthieuDartiailh
left a comment
Owner
There was a problem hiding this comment.
Thanks for the very well explained issue and patch. I will try to release next week.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Python 3.14, round-tripping code with two consecutive
async forloops whose bodies contain atry/exceptfails during stack-size computation:A single such loop works, and Python 3.11–3.13 are unaffected. We hit this in production through ddtrace's Code Origin for Spans, which rewrites functions with this library.
Root cause
Since 3.14,
END_ASYNC_FORhas an oparg and is inopcode.hasjump, and since #179 bytecode treats it as a conditional backward jump. The interpreter never takes that jump:_END_ASYNC_FORinPython/bytecodes.cdoesJUMPBY(0); // Pretend jump as we need source offset for monitoring. The oparg only letsINSTRUMENTED_END_ASYNC_FORreport the branch source tosys.monitoring. CPython's own stack-depth pass skips this edge (Python/flowgraph.c,calculate_stackdepth:HAS_TARGET(opcode) && opcode != END_ASYNC_FOR)._StackSizeComputerfollowed the edge into the loop'sSEND/END_SENDblock at the wrong depth and with the enclosingTryBeginstill open. For the second loop that block starts with anotherTryBegin, which trips the non-nesting assertion.Fix
MONITORING_ONLY_JUMP_OPS({END_ASYNC_FOR}on 3.14+, empty otherwise) ininstr.py._StackSizeComputer.run.has_jump()and the other jump classifications are unchanged, because the target is still needed for labels and oparg encoding.Tests
test_stack_size_computation_consecutive_async_for_try_except. It fails without the fix on 3.14 and passes on 3.12, 3.13 and 3.14.co_stacksizefor nestedasync for, async comprehensions, andasync with+async forwith try/finally.