Strange disassembly
Chris Angelico
rosuav at gmail.com
Fri Jun 18 20:13:33 EDT 2021
On Sat, Jun 19, 2021 at 9:50 AM Terry Reedy <tjreedy at udel.edu> wrote:
> > Why are there two separate bytecode blocks for the "raise Exception"?
>
> Because one block must POP_TOP and other must not.
>
> > 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.
>
> To reuse the exception block with POP_TOP, could jump over it after the
> 2nd compare.
Hmm, fair enough I guess. The compiler figured that it'd be faster to
duplicate the executable code rather than have the jump. It made for a
somewhat confusing disassembly, but I presume it's faster to run.
> For the simplest and fasted bytecode, write normal logic and let x be
> reloaded instead of duplicated and rotated.
>
> >>> import dis
> >>> def f(x):
> ... if x <= 0 or 10 <= x: raise Exception
> ...
> ...
> >>> dis.dis(f)
> 2 0 LOAD_FAST 0 (x)
> 2 LOAD_CONST 1 (0)
> 4 COMPARE_OP 1 (<=)
> 6 POP_JUMP_IF_TRUE 8 (to 16)
> 8 LOAD_CONST 2 (10)
> 10 LOAD_FAST 0 (x)
> 12 COMPARE_OP 1 (<=)
> 14 POP_JUMP_IF_FALSE 10 (to 20)
> >> 16 LOAD_GLOBAL 0 (Exception)
> 18 RAISE_VARARGS 1
> >> 20 LOAD_CONST 0 (None)
> 22 RETURN_VALUE
> >>>
>
Makes sense. I'm not sure if this would actually run faster, but I
can't really justify warping my code around the disassembly :)
Thanks for the explanation. I guess I just assumed the interpreter
would prefer a jump to the duplication, but that's a decision it's
free to take!
ChrisA
More information about the Python-list
mailing list