Hi all,

I am the current maintainer of bytecode (https://github.com/MatthieuDartiailh/bytecode) which is a library to perform assembly and disassembly of Python bytecode. The library was created by V. Stinner.

I started looking in Python 3.11 support in bytecode, I read Objects/exception_handling_notes.txt and I have a couple of questions regarding the exception table:

Currently bytecode exposes three level of abstractions:
  - the concrete level in which one deals with instruction offset for jumps and explicit indexing into the known constants and names   - the bytecode level which uses labels for jumps and allow non integer argument to instructions   - the cfg level which provides basic blocks delineation over the bytecode level

So my first idea was to directly expose the unpacked exception table (start, stop, target, stack_depth, last_i) at the concrete level and use pseudo-instruction and labels at the bytecode level. At this point of my reflections, I saw https://github.com/python/cpython/commit/c57aad777afc6c0b382981ee9e4bc94c03bf5f68 about adding pseudo-instructionto dis output in 3.12 and though it would line up quite nicely. Reading through, I got curious about how SETUP_WITH handled popping one extra item from the stack so I went to look at dis results on a couple of small examples. I tried on 3.10 and 3.11b3 (for some reasons I cannot compile main at a391b74d on windows).

I looked at simple things and got a bit surprised:

Disassembling:
deff():
try:
a= 1
except:
raise

I get on 3.11:
 1           0 RESUME                   0

  2           2 NOP

  3           4 LOAD_CONST               1 (1)
              6 STORE_FAST               0 (a)
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE
        >>   12 PUSH_EXC_INFO

  4          14 POP_TOP

  5          16 RAISE_VARARGS            0
        >>   18 COPY                     3
             20 POP_EXCEPT
             22 RERAISE                  1
ExceptionTable:
  4 to 6 -> 12 [0]
  12 to 16 -> 18 [1] lasti

On 3.10:
  2           0 SETUP_FINALLY            5 (to 12)

  3           2 LOAD_CONST               1 (1)
              4 STORE_FAST               0 (a)
              6 POP_BLOCK
              8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

  4     >>   12 POP_TOP
             14 POP_TOP
             16 POP_TOP

  5          18 RAISE_VARARGS            0

This surprised me on two levels:
- first I have never seen the RESUME opcode and it is currently not documented - my second surprise comes from the second entry in the exception table. At first I failed to see why it was needed but writing this I realize it corresponds to the explicit handling of exception propagation to the caller. Since I cannot compile 3.12 ATM I am wondering how this plays with pseudo-instruction: in particular are pseudo-instructions generated for all entries in the exception table ?

My initial idea was to have a SETUP_FINALLY/SETUP_CLEANUP - POP_BLOCK pair for each line in the exception table and label for the jump target. But I realize it means we will have many such pairs than in 3.10. It is fine by me but I wondered what choice was made in 3.12 dis and if this approach made sense.

Best regards

Matthieu
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/XZ7KDCI3TXEUERU3YIFKC543GAGIYG6Q/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to