[New-bugs-announce] [issue46724] Odd Bytecode Generation in 3.10

Saul Shanabrook report at bugs.python.org
Fri Feb 11 12:22:26 EST 2022


New submission from Saul Shanabrook <s.shanabrook at gmail.com>:

I noticed that in Python 3.10, and also in main, a certain control flow construct produces some very odd bytecode (showing on main but same on python 3.10 tags):

```
./python.exe -c 'import dis; dis.dis("while not (a < b < c): pass")'
              0 RESUME                   0

  1           2 LOAD_NAME                0 (a)
              4 LOAD_NAME                1 (b)
              6 SWAP                     2
              8 COPY                     2
             10 COMPARE_OP               0 (<)
             12 POP_JUMP_IF_FALSE       11 (to 22)
             14 LOAD_NAME                2 (c)
             16 COMPARE_OP               0 (<)
             18 POP_JUMP_IF_TRUE        28 (to 56)
             20 JUMP_FORWARD             1 (to 24)
        >>   22 POP_TOP
        >>   24 LOAD_NAME                0 (a)
             26 LOAD_NAME                1 (b)
             28 SWAP                     2
             30 COPY                     2
             32 COMPARE_OP               0 (<)
             34 POP_JUMP_IF_FALSE       23 (to 46)
             36 LOAD_NAME                2 (c)
             38 COMPARE_OP               0 (<)
             40 POP_JUMP_IF_FALSE       12 (to 24)
             42 LOAD_CONST               0 (None)
             44 RETURN_VALUE
        >>   46 POP_TOP
             48 EXTENDED_ARG           255
             50 EXTENDED_ARG         65535
             52 EXTENDED_ARG         16777215
             54 JUMP_FORWARD         4294967280 (to 8589934616)
        >>   56 LOAD_CONST               0 (None)
             58 RETURN_VALUE
```

The last JUMP_FORWARD has a rather larger argument! This was the minimal example I could find to replicate this.

However, this is an example of some runnable code that also encounters it:

```
a = b = c = 1
while not (a < b < c):
    if c == 1:
        c = 3
    else:
        b = 2
    print(a, b, c)
```

This actually executes fine, but I notice that when it's executing it does execute that very large arg, but that the `oparg` to JUMP_FORWARD ends up being negative! By adding some tracing, I was able to see that the `oparg` variable in the `TARGET(JUMP_FORWARD)` case is `-32`.

I am not sure if this is a bug or intended behavior. It does seem a bit odd to have this unnecessarily large argument that ends up turning into a negative jump! But the behavior seems fine.

At the least, maybe `dis` should be modified so that it properly sees this as a negative jump and debugs it properly? I am happy to submit a PR to modify `dis` to handle this case, but I also wanted to flag that maybe it's a bug to being with.

----------
components: Interpreter Core
messages: 413088
nosy: saulshanabrook
priority: normal
severity: normal
status: open
title: Odd Bytecode Generation in 3.10
versions: Python 3.10, Python 3.11

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue46724>
_______________________________________


More information about the New-bugs-announce mailing list