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@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
--
https://mail.python.org/mailman/listinfo/python-list