[Subversion] / BytecodeAssembler / README.txt  

Diff of /BytecodeAssembler/README.txt

Parent Directory | Revision Log

version 2629, Mon Aug 2 19:08:08 2010 UTC version 2630, Mon Aug 2 19:27:33 2010 UTC
Line 18 
Line 18 
   
 .. _BytecodeAssembler reference manual: http://peak.telecommunity.com/DevCenter/BytecodeAssembler#toc  .. _BytecodeAssembler reference manual: http://peak.telecommunity.com/DevCenter/BytecodeAssembler#toc
   
 Changes since version 0.5.2:  
   
 * Symbolic disassembly with full emulation of backward-compatible JUMP_IF_TRUE  Changes since version 0.5.2:
   and JUMP_IF_FALSE opcodes on Python 2.7 -- tests now run clean on Python 2.7.  
   
   * Symbolic disassembly with full emulation of backward-compatible
     ``JUMP_IF_TRUE`` and ``JUMP_IF_FALSE`` opcodes on Python 2.7 -- tests now
     run clean on Python 2.7.
   
   * Support for backward emulation of Python 2.7's ``JUMP_IF_TRUE_OR_POP`` and
     ``JUMP_IF_FALSE_OR_POP`` instructions on earlier Python versions; these
     emulations are also used in BytecodeAssembler's internal code generation,
     for maximum performance on 2.7+ (with no change to performance on older
     versions).
   
 Changes since version 0.5.1:  Changes since version 0.5.1:
   
Line 865 
Line 872 
     AssertionError: Label previously defined      AssertionError: Label previously defined
   
   
   More Conditional Jump Instructions
   ----------------------------------
   
   In Python 2.7, the traditional ``JUMP_IF_TRUE`` and ``JUMP_IF_FALSE``
   instructions were replaced with four new instructions that either conditionally
   or unconditionally pop the value being tested.  This was done to improve
   performance, since virtually all conditional jumps in Python code pop the
   value on one branch or the other.
   
   To provide better cross-version compatibility, BytecodeAssembler emulates the
   old instructions on Python 2.7 by emitting a ``DUP_TOP`` followed by a
   ``POP_JUMP_IF_FALSE`` or ``POP_JUMP_IF_TRUE`` instruction.
   
   However, since this decreases performance, BytecodeAssembler *also* emulates
   Python 2.7's ``JUMP_IF_FALSE_OR_POP`` and ``JUMP_IF_FALSE_OR_TRUE`` opcodes
   on *older* Pythons::
   
       >>> c = Code()
       >>> l1, l2 = Label(), Label()
       >>> c(99, l1.JUMP_IF_FALSE_OR_POP, Return(27), l1)
       >>> c(l2.JUMP_IF_TRUE_OR_POP, Return(42), l2, Code.RETURN_VALUE)
       >>> dump(c.code())
                       LOAD_CONST               1 (99)
                       JUMP_IF_FALSE           L1
                       POP_TOP
                       LOAD_CONST               2 (27)
                       RETURN_VALUE
               L1:     JUMP_IF_TRUE            L2
                       POP_TOP
                       LOAD_CONST               3 (42)
                       RETURN_VALUE
               L2:     RETURN_VALUE
   
   This means that you can immediately begin using the "or-pop" variations, in
   place of a jump followed by a pop, and BytecodeAssembler will use the faster
   single instruction automatically on Python 2.7+.
   
   BytecodeAssembler *also* supports using Python 2.7's conditional jumps
   that do unconditional pops, but currently cannot emulate them on older Python
   versions, so at the moment you should use them only when your code requires
   Python 2.7.
   
   (Note: for ease in doctesting across Python versions, the ``dump()`` function
   *always* shows the code as if it were generated for Python 2.6 or lower, so
   if you need to check the *actual* bytecodes generated, you must use Python's
   ``dis.dis()`` function instead!)
   
   
 N-Way Comparisons  N-Way Comparisons
 -----------------  -----------------
   
Line 1287 
Line 1342 
     ...             if const_value(value):      ...             if const_value(value):
     ...                 continue        # true constants can be skipped      ...                 continue        # true constants can be skipped
     ...         except NotAConstant:    # but non-constants require code      ...         except NotAConstant:    # but non-constants require code
     ...             code(value, end.JUMP_IF_FALSE, Code.POP_TOP)      ...             code(value, end.JUMP_IF_FALSE_OR_POP)
     ...         else:       # and false constants end the chain right away      ...         else:       # and false constants end the chain right away
     ...             return code(value, end)      ...             return code(value, end)
     ...     code(values[-1], end)      ...     code(values[-1], end)
Line 1617 
Line 1672 
     ...         return cond, then, else_      ...         return cond, then, else_
     ...     else_clause = Label()      ...     else_clause = Label()
     ...     end_if = Label()      ...     end_if = Label()
     ...     code(cond, else_clause.JUMP_IF_FALSE, Code.POP_TOP, then)      ...     code(cond, else_clause.JUMP_IF_FALSE_OR_POP, then)
     ...     code(end_if.JUMP_FORWARD, else_clause, Code.POP_TOP, else_)      ...     code(end_if.JUMP_FORWARD, else_clause, Code.POP_TOP, else_)
     ...     code(end_if)      ...     code(end_if)
     >>> If = nodetype()(If)      >>> If = nodetype()(If)
Line 1650 
Line 1705 
     ...         return cond, then, else_      ...         return cond, then, else_
     ...     else_clause = Label()      ...     else_clause = Label()
     ...     end_if = Label()      ...     end_if = Label()
     ...     code(cond, else_clause.JUMP_IF_FALSE, Code.POP_TOP, then)      ...     code(cond, else_clause.JUMP_IF_FALSE_OR_POP, then)
     ...     if code.stack_size is not None:      ...     if code.stack_size is not None:
     ...         end_if.JUMP_FORWARD(code)      ...         end_if.JUMP_FORWARD(code)
     ...     code(else_clause, Code.POP_TOP, else_, end_if)      ...     code(else_clause, Code.POP_TOP, else_, end_if)
Line 2602 
Line 2657 
     >>> c = Code()      >>> c = Code()
     >>> else_ = Label()      >>> else_ = Label()
     >>> end = Label()      >>> end = Label()
     >>> c(99, else_.JUMP_IF_TRUE, Code.POP_TOP, end.JUMP_FORWARD)      >>> c(99, else_.JUMP_IF_TRUE_OR_POP, end.JUMP_FORWARD)
     >>> c(else_, Code.POP_TOP, end)      >>> c(else_, Code.POP_TOP, end)
     >>> dump(c.code())      >>> dump(c.code())
                     LOAD_CONST               1 (99)                      LOAD_CONST               1 (99)
Line 2614 
Line 2669 
     >>> c.stack_size      >>> c.stack_size
     0      0
     >>> if sys.version>='2.7':      >>> if sys.version>='2.7':
     ...     print c.stack_history == [0, 1, 1, 1, 2, 1, 1, 1, 0, None, None, 1]      ...     print c.stack_history == [0, 1, 1, 1,    0, 0, 0, None, None, 1]
     ... else:      ... else:
     ...     print c.stack_history == [0, 1, 1, 1,    1, 1, 1, 0, None, None, 1]      ...     print c.stack_history == [0, 1, 1, 1,    1, 1, 1, 0, None, None, 1]
     True      True


Generate output suitable for use with a patch program
Legend:
Removed from v.2629  
changed lines
  Added in v.2630

cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help