GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Bytecode positions seem way too broad · Issue #93691 · python/cpython

Bytecode positions seem way too broad #93691

New issue
Copy link
New issue
Copy link
Closed
Closed
Bytecode positions seem way too broad#93691
Copy link
Assignees
iritkatriel
Labels
3.11only security fixesonly security fixes3.12only security fixesonly security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@brandtbucher
brandtbucher
opened on Jun 10, 2022
Issue body actions

(Note that dis currently has a bug in displaying accurate location info in the presence of CACHEs. The correct information can be observed by working with co_positions directly or using the code from that PR.)

While developing specialist, I realized that there are lots of common code patterns that produce bytecode with unexpectedly large source ranges. In addition to being unhelpful for both friendly tracebacks (the original motivation) and things like bytecode introspection, I suspect these huge ranges may also be bloating the size of our internal position tables as well.

Consider the following function:

def analyze(path):                         #  1
    upper = lower = total = 0              #  2
    with open(path) as file:               #  3
        for line in file:                  #  4
            for character in line:         #  5
                if character.isupper():    #  6
                    upper += 1             #  7
                elif character.islower():  #  8
                    lower += 1             #  9
                total += 1                 # 10
    return lower / total, upper / total    # 11


import dis
from pprint import pprint as pp
def pos(p):
    return (p.lineno, p.end_lineno, p.col_offset, p.end_col_offset)

pp([(pos(x.positions), x.opname, x.argval) for x in dis.get_instructions(analyze)])

Things that should probably span one line at most:

  • The first GET_ITER/FOR_ITER pair span all of lines 4 through 10.
  • The second GET_ITER/FOR_ITER pair spans all of lines 5 through 10.
  • The first POP_JUMP_FORWARD_IF_FALSE spans all of lines 6 through 9.
  • The second POP_JUMP_FORWARD_IF_FALSE spans all of lines 8 through 9.
  • Ten instructions for with cleanup each span all of lines 3 through 10.

Things that should probably be artificial:

  • A JUMP_FORWARD spans all of line 7.
  • The first JUMP_BACKWARD spans all of line 10.
  • The second JUMP_BACKWARD spans all of lines 5 through 10.

Things I don't get:

  • A NOP spans all of lines 4 through 10.

As a result, over half of the generated bytecode for this function claims to span line 9, for instance. Also not shown here: the instructions for building functions and classes have similarly huge spans.

I think this can be tightened up in the compiler by:

  • Being more aggressive in calling SET_LOC on child nodes.
  • Being more aggressive in calling UNSET_LOC before unconditional jumps.

Linked PRs

  • gh-93691: fix too broad source locations of with-statement instructions #120125
  • gh-93691: fix too broad source locations of for statement iterators #120330
  • [3.13] gh-93691: fix too broad source locations of for statement iterators (GH-120330) #120399
  • [3.12] gh-93691: fix too broad source locations of for statement iterators (GH-120330 #120405
  • [3.13] gh-93691: fix too broad source locations of with-statement instructions (GH-120125) #123604
  • [3.12] gh-93691: fix too broad source locations of with-statement instructions (GH-120125) #123605

Activity

Next
  1. brandtbucher
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
    3.11only security fixesonly security fixes
    3.12only security fixesonly security fixes
    on Jun 10, 2022
  2. brandtbucher commented on Jun 10, 2022

    @brandtbucher
    brandtbucher
    on Jun 10, 2022
    MemberAuthor
    More actions

    I can perhaps see why the argument could be made that we should have the location info for certain constructs span their entire block or jump range, but to me this just feels like the shape of the AST and the design of the compiler are leaking into the bytecode more than is really helpful in practice.

  3. brandtbucher commented on Jun 10, 2022

    @brandtbucher
    brandtbucher
    on Jun 10, 2022
    MemberAuthor
    More actions

    @pablogsal @markshannon @iritkatriel

  4. brandtbucher commented on Jun 10, 2022

    @brandtbucher
    brandtbucher
    on Jun 10, 2022
    MemberAuthor
    More actions

    As a quick-and-dirty experiment: for the given example function, setting node.end_lineno = node.lineno on every node before compiling the AST resulted in a 20% reduction in the size of co_linetable.

  5. pablogsal commented on Jun 10, 2022

    @pablogsal
    pablogsal
    on Jun 10, 2022
    Member
    More actions

    I can perhaps see why the argument could be made that we should have the location info for certain constructs span their entire block or jump range, but to me this just feels like the shape of the AST and the design of the compiler are leaking into the bytecode more than is really helpful in practice.

    I don't think that many of these things were conscious decisions. Originally we added and enabled the infrastructure so the debug information could be propagated and we spent some time doing small optimisations, but we are missing a full pass over the compiler to fix things like this. Additionally, there are many instructions that don't really benefit from having position information because they are either artificial or don't map well to source code.

    I think this is a very good find. With what seems like a small tedious amount of work we could reduce substantially the size for some functions, specially in block setup stuff.

    Thanks for opening the issue and the insights @brandtbucher, this is very interesting indeed.

  6. markshannon commented on Jun 13, 2022

    @markshannon
    markshannon
    on Jun 13, 2022
    Member
    More actions

    I don't think the shape of the AST is "leaking" into the bytecode. The AST defines the locations.
    The problem is, IMO, in the design of the compiler. Tracking the "current" location in the compiler only makes sense if the bytecode is produced in a linear fashion, which it clearly isn't.

    We should make the location used explicit when generating code, not use the implicit location stored in the compiler.
    ADDOP(opcode, oparg, location)

  7. brandtbucher
    moved this to In Progress in Fancy CPython Boardon Jun 15, 2022
  8. brandtbucher
    added this to Fancy CPython Boardon Jun 15, 2022
  9. brandtbucher
    assigned
    brandtbucher
    and unassigned
    brandtbucher
    on Jun 15, 2022
  10. brandtbucher
    moved this from In Progress to Todo in Fancy CPython Boardon Jun 20, 2022
  11. iritkatriel
    self-assigned this
    on Sep 30, 2022
  12. 4 remaining items

  13. iritkatriel
    added 2 commits that reference this issue on Jun 10, 2024

    pythongh-93691: fix too broad source locations of for statement itera…

    de8e529

    gh-93691: fix too broad source locations of for statement iterators (#…

    97b69db
  14. miss-islington
    added a commit that references this issue on Jun 12, 2024

    pythongh-93691: fix too broad source locations of for statement itera…

    4994eaf
  15. iritkatriel
    added 3 commits that reference this issue on Jun 12, 2024

    [3.13] gh-93691: fix too broad source locations of for statement iter…

    39825a7

    [3.12] pythongh-93691: fix too broad source locations of for statemen…

    dba9b0c

    [3.12] gh-93691: fix too broad source locations of for statement iter…

    5a6cc3c
  16. iritkatriel
    closed this as completedon Jun 13, 2024
  17. github-project-automation
    moved this from Todo to Done in Fancy CPython Boardon Jun 13, 2024
  18. mrahtz
    added a commit that references this issue on Jun 30, 2024

    pythongh-93691: fix too broad source locations of for statement itera…

    0808b02
  19. estyxx
    added 2 commits that reference this issue on Jul 17, 2024

    pythongh-93691: fix too broad source locations of with-statement inst…

    e9cefff

    pythongh-93691: fix too broad source locations of for statement itera…

    e0de365
  20. miss-islington
    added 2 commits that reference this issue on Sep 2, 2024

    pythongh-93691: fix too broad source locations of with-statement inst…

    0da05d4

    pythongh-93691: fix too broad source locations of with-statement inst…

    35f1856
  21. iritkatriel
    added 2 commits that reference this issue on Sep 2, 2024

    [3.12] gh-93691: fix too broad source locations of with-statement ins…

    22ec9cb

    [3.13] gh-93691: fix too broad source locations of with-statement ins…

    494181e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

  • @iritkatriel
    iritkatriel

Labels

3.11only security fixesonly security fixes3.12only security fixesonly security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.