gh-151321: Fix opcode metadata flags for LOAD_DEREF and LOAD_CLOSURE#151386
Draft
harjothkhara wants to merge 2 commits into
Draft
gh-151321: Fix opcode metadata flags for LOAD_DEREF and LOAD_CLOSURE#151386harjothkhara wants to merge 2 commits into
harjothkhara wants to merge 2 commits into
Conversation
…OSURE LOAD_DEREF and LOAD_CLOSURE were missing HAS_FREE_FLAG in the generated opcode metadata, and both also carried HAS_LOCAL_FLAG, so dis.hasfree no longer reported them while dis.haslocal wrongly included them. This regressed the documented dis.hasfree / dis.haslocal contract: LOAD_CLOSURE broke in 3.13 (when it became a pseudo-op inheriting LOAD_FAST's flags) and LOAD_DEREF broke in 3.14 (when it started using _PyCell_GetStackRef, which the cases generator's has_free heuristic did not recognize). Teach the cases generator to treat _PyCell_GetStackRef as a free-variable access, and give the LOAD_CLOSURE pseudo an explicit HAS_FREE flag. A pseudo that explicitly accesses a free variable now suppresses the inherited HAS_LOCAL, mirroring the existing "uses_locals and not has_free" rule for real instructions, so HAS_FREE and HAS_LOCAL are never both set. The change is to introspection metadata only; the generated interpreter and optimizer code are unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
a0a2d2f to
9ea5992
Compare
Contributor
Author
|
The remaining CI failure appears unrelated to this PR. The failing job is Windows (free-threading) / Build and test (x64, switch-case): It failed in: This PR only changes opcode metadata/generation and test__opcode. I also reran the focused test locally after updating the branch onto current main, and it passed 6/6 times on my local macOS debug build. Could someone with Actions permissions rerun the failed Windows job? |
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.
Summary
LOAD_DEREFandLOAD_CLOSUREwere missingHAS_FREE_FLAGin the generated opcode metadata, and both also carriedHAS_LOCAL_FLAG. As a resultdis.hasfreeno longer reported them anddis.haslocalwrongly included them — breaking the documenteddis.hasfree/dis.haslocalcontract.LOAD_CLOSUREregressed in 3.13 (when it became a pseudo-op inheritingLOAD_FAST's flags);LOAD_DEREFregressed in 3.14 (when it began using_PyCell_GetStackRef, which the cases generator'shas_freeheuristic didn't recognize). This restores the named 3.12 behavior. Surface: introspection metadata only — the generated interpreter/optimizer code is unchanged.The cases generator now treats
_PyCell_GetStackRefas a free-variable access, and theLOAD_CLOSUREpseudo gets an explicitHAS_FREE. A pseudo that explicitly accesses a free variable now suppresses the inheritedHAS_LOCAL, mirroring the existinguses_locals and not has_freerule for real instructions (the"HAS_FREE" in self.flagsguard is deliberate — the explicit pseudo flags are stored as name strings).Verification
make regen-all→git statusclean (no generated churn beyond the intended opcode/uop metadata flag lines;generated_cases.c.h,executor_cases.c.h,_opcode_metadata.pyunchanged)../python.exe -m test test__opcode test_dis test_compile→ SUCCESS (342 tests)._PyCell_GetStackRefhas exactly one consumer (LOAD_DEREF), so no other opcode's flags change.Real behavior proof
dis.hasfree/dis.haslocalmisclassifyLOAD_DEREFandLOAD_CLOSURE../python.exe(--with-pydebug) from this branch on macOS arm64.dis.hasfreeand neither is indis.haslocal; thehasfreeset now lists the six named free/cell opcodes, restoring the named 3.12 classification.HAS_FREE/HAS_LOCALflags feed only_opcode/dis); not built on Windows/Linux or on free-threading/JIT configs (CI will cover those). Backport split noted below.Backport
The broken-version set differs per opcode:
LOAD_DEREFregressed after 3.13;LOAD_CLOSUREis broken on 3.13 too. Requestingneeds backport to 3.13and3.14.Note that this diff will not cherry-pick cleanly to 3.13: on 3.13
LOAD_DEREFstill usesPyCell_GetRef(already correctly detected ashas_free), so the_PyCell_GetStackRefline is inapplicable there. 3.14 takes the full diff; 3.13 likely needs aLOAD_CLOSURE-only manual backport (the pseudo flag + theanalyzer.pypseudo change).