0db046b67b
The search in these cases should include all finally handlers that are after the current ip. If a handler starts at exactly ip then it is considered "after" the ip. This can happen when END_FINALLY is followed immediately by a finally handler (from a different finally). Consider the function: def f(): try: return 0 finally: print(1) The current bytecode emitter generates the following code: 00 SETUP_FINALLY 5 02 LOAD_CONST_SMALL_INT 0 03 RETURN_VALUE 04 LOAD_CONST_NONE **** 05 LOAD_GLOBAL print 07 LOAD_CONST_SMALL_INT 1 08 CALL_FUNCTION n=1 nkw=0 10 POP_TOP 11 END_FINALLY 12 LOAD_CONST_NONE 13 RETURN_VALUE The LOAD_CONST_NONE marked with **** is dead code because it follows a RETURN_VALUE, and nothing jumps to this LOAD_CONST_NONE. If the emitter could remove this this dead code it would produce: 00 SETUP_FINALLY 4 02 LOAD_CONST_SMALL_INT 0 03 RETURN_VALUE 04 LOAD_GLOBAL print 06 LOAD_CONST_SMALL_INT 1 07 CALL_FUNCTION n=1 nkw=0 09 POP_TOP 10 END_FINALLY 11 LOAD_CONST_NONE 12 RETURN_VALUE In this case the finally block (which starts at offset 4) immediately follows the RETURN_VALUE. When RETURN_VALUE executes ip will point to offset 4 in the bytecode (because the dispatch of the opcode does *ip++) and so the finally handler will only be found if a >= comparison is used. It's a similar story for break/continue: while True: try: break finally: print(1) Although technically in this case the > comparison still works because the extra byte from the UNWIND_JUMP (encoding the number of exception handlers to unwind) doesn't have a *ip++ (just a *ip) so ip remains pointing within the UNWIND_JUMP opcode, and not at the start of the following finally handler. Nevertheless, the change is made to use >= for consistency with the RETURN_VALUE change. Signed-off-by: Damien George <damien@micropython.org>