I was trying to find out more about some aspects of the new exception table introduced in Python 3.11. In particular, I was trying to find out when one would need to set
lasti for an entry in the table. Looking at the code in
ceval.c I came to the conclusion that, at the moment, the only consumer of
lasti from the stack would be the
RERAISE opcode, when the oparg is non-zero. So if the exception table has an entry with a jump to an offset where a
RERAISE with a non-zero oparg would be executed, one would have to ensure that the
lasti bit is set.
Is this correct? Is this perhaps documented somewhere I haven’t been able to look at? I know that there is cpython/exception_handling_notes.txt at main · python/cpython · GitHub on the topic, but I think it might be good to expand a bit more on the
@iritkatriel I hope you don’t mind me tagging you as I think you are one of the core devs who might know the answer to this.
I assume you’ve guessed right, but I don’t know for sure. Like most other aspects of bytecode, the exception table is not part of any stable or documented API. There is some discussion of lasti in the bpo issue for the change, Issue 40222: "Zero cost" exception handling - Python tracker.
The compiler currently determines whether to set the lasti bit based on whether a SETUP_WITH or SETUP_CLEANUP pseudo-instruction exists in the setup block; like SETUP_FINALLY and POP_BLOCK, these don’t correspond to real instructions but cause exception table entries to be created using a patented and proprietary algorithm.
Like your other question, it would be better if you didn’t need to know the answer, because in 3.12 things will probably be different again. Hopefully you will then be the beneficiary of a documented, stable API – PEP 669. Until then, you can read the source code just as easily as I can.
Like most other aspects of bytecode, the exception table is not part of any stable or documented API.
Indeed I was hoping for some more details in the note file that I mentioned so that I wouldn’t have had to “guess” when it is needed, just in case I misread the source code around it
Like your other question, it would be better if you didn’t need to know the answer, because in 3.12 things will probably be different again.
It would be great if I could not rely on these internal details, but the products I’m working on require me to do things at the bytecode level (simply monkey-patching wouldn’t work for me because of the cost of chasing references at runtime). That’s why it is important for me (and I suppose for those who maintain projects with similar needs, e.g. the
bytecode package, too) to be able to locate this information, one way or another. Ultimately, the source code is the documentation, but having these details spelled out in existing notes like
exception_handling_notes.txt might provide a shortcut to save some time
If you want to help, you could submit a PR that adds something to that text file that will clarify it for the next person who comes along. If you CC me I will be sure to review it.
Thanks! Indeed that’s what I was thinking of doing next, but I wanted to make sure first that wasn’t going to propose incorrect changes. I’ll submit one within the next couple of days.
Great! There are no guarantees in life, but maybe if you add Mark Shannon to the reviewer list he’ll correct your gravest mistakes.