Strange disassembly

Rob Cliffe rob.cliffe at btinternet.com
Sat Jun 19 03:00:37 EDT 2021



On 19/06/2021 07:50, Chris Angelico wrote:
> On Sat, Jun 19, 2021 at 4:16 PM Rob Cliffe via Python-list
> <python-list at python.org> wrote:
>>
>>
>> On 18/06/2021 11:04, Chris Angelico wrote:
>>>>>> sys.version
>>> '3.10.0b2+ (heads/3.10:33a7a24288, Jun  9 2021, 20:47:39) [GCC 8.3.0]'
>>>>>> def chk(x):
>>> ...     if not(0 < x < 10): raise Exception
>>> ...
>>>>>> dis.dis(chk)
>>>     2           0 LOAD_CONST               1 (0)
>>>                 2 LOAD_FAST                0 (x)
>>>                 4 DUP_TOP
>>>                 6 ROT_THREE
>>>                 8 COMPARE_OP               0 (<)
>>>                10 POP_JUMP_IF_FALSE       11 (to 22)
>>>                12 LOAD_CONST               2 (10)
>>>                14 COMPARE_OP               0 (<)
>>>                16 POP_JUMP_IF_TRUE        14 (to 28)
>>>                18 LOAD_GLOBAL              0 (Exception)
>>>                20 RAISE_VARARGS            1
>>>           >>   22 POP_TOP
>>>                24 LOAD_GLOBAL              0 (Exception)
>>>                26 RAISE_VARARGS            1
>>>           >>   28 LOAD_CONST               0 (None)
>>>                30 RETURN_VALUE
>>> Why are there two separate bytecode blocks for the "raise Exception"?
>>> I'd have thought that the double condition would still be evaluated as
>>> one thing, or at least that the jump destinations for both the
>>> early-abort and the main evaluation should be the same.
>>>
>>> ChrisA
>> As an ornery human I could refactor this to avoid the code duplication as
>>
>>     2           0 LOAD_CONST               1 (0)
>>                 2 LOAD_FAST                0 (x)
>>                 4 DUP_TOP
>>                 6 ROT_THREE
>>                 8 COMPARE_OP               0 (<)
>>                10 POP_JUMP_IF_TRUE        10 (to 18)
>>                12 POP_TOP
>>           >>   14 LOAD_GLOBAL              0 (Exception)
>>                16 RAISE_VARARGS            1
>>           >>   18 LOAD_CONST               2 (10)
>>                20 COMPARE_OP               0 (<)
>>                22 POP_JUMP_IF_FALSE       21 (to 14)
>>                24 LOAD_CONST               0 (None)
>>                26 RETURN_VALUE
>>   >>>
>>
>> (there may be mistakes in this) but this is probably too much to expect
>> of the compiler.
> Hmm, I think that depends too much on knowing that the raise won't
> return. That might be a neat optimization (effectively a form of dead
> code removal), but otherwise, the best you could do would be to also
> have it jump out after the raise.
>
> ChrisA
Er, doesn't your original dis output make the same assumption? 
Otherwise, after this line

               20 RAISE_VARARGS            1

it would attempt to do an extra pop, then raise a second time.
Rob Cliffe



More information about the Python-list mailing list