[Python-Dev] Wither PEP 335 (Overloadable Boolean Operators)?

Greg Ewing greg.ewing at canterbury.ac.nz
Fri May 25 04:05:35 CEST 2007


Guido van Rossum wrote:

> Last call for discussion! I'm tempted to reject this -- the ability to
> generate optimized code based on the shortcut semantics of and/or is
> pretty important to me.

Please don't be hasty. I've had to think about this issue
a bit.

The conclusion I've come to is that there may be a small loss
in the theoretical amount of optimization opportunity available,
but not much. Furthermore, if you take into account some other
improvements that can be made (which I'll explain below) the
result is actually *better* than what 2.5 currently generates.

For example, Python 2.5 currently compiles

   if a and b:
     <stats>

into

     <evaluate a>
     JUMP_IF_FALSE L1
     POP_TOP
     <evaluate b>
     JUMP_IF_FALSE L1
     POP_TOP
     <stats>
     JUMP_FORWARD L2
   L1:
     15 POP_TOP
   L2:

Under my PEP, without any other changes, this would become

     <evaluate a>
     LOGICAL_AND_1 L1
     <evaluate b>
     LOGICAL_AND_2
   L1:
     JUMP_IF_FALSE L2
     POP_TOP
     <stats>
     JUMP_FORWARD L3
   L2:
     15 POP_TOP
   L3:

The fastest path through this involves executing one extra
bytecode. However, since we're not using JUMP_IF_FALSE to
do the short-circuiting any more, there's no need for it
to leave its operand on the stack. So let's redefine it and
change its name to POP_JUMP_IF_FALSE. This allows us to
get rid of all the POP_TOPs, plus the jump at the end of
the statement body. Now we have

     <evaluate a>
     LOGICAL_AND_1 L1
     <evaluate b>
     LOGICAL_AND_2
   L1:
     POP_JUMP_IF_FALSE L2
     <stats>
   L2:

The fastest path through this executes one *less* bytecode
than in the current 2.5-generated code. Also, any path that
ends up executing the body benefits from the lack of a
jump at the end.

The same benefits also result when the boolean expression is
more complex, e.g.

   if a or b and c:
     <stats>

becomes

     <evaluate a>
     LOGICAL_OR_1 L1
     <evaluate b>
     LOGICAL_AND_1 L2
     <evaluate c>
     LOGICAL_AND_2
   L2:
     LOGICAL_OR_2
   L1:
     POP_JUMP_IF_FALSE L3
     <stats>
   L3:

which contains 3 fewer instructions overall than the
corresponding 2.5-generated code.

So I contend that optimization is not an argument for
rejecting this PEP, and may even be one for accepting
it.

--
Greg


More information about the Python-Dev mailing list