home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 June / maximum-cd-2011-06.iso / DiscContents / LibO_3.3.1_Win_x86_install_multi.exe / libreoffice1.cab / test_peepholer.py < prev    next >
Encoding:
Python Source  |  2011-02-15  |  7.9 KB  |  224 lines

  1. import dis
  2. import sys
  3. from cStringIO import StringIO
  4. import unittest
  5.  
  6. def disassemble(func):
  7.     f = StringIO()
  8.     tmp = sys.stdout
  9.     sys.stdout = f
  10.     dis.dis(func)
  11.     sys.stdout = tmp
  12.     result = f.getvalue()
  13.     f.close()
  14.     return result
  15.  
  16. def dis_single(line):
  17.     return disassemble(compile(line, '', 'single'))
  18.  
  19. class TestTranforms(unittest.TestCase):
  20.  
  21.     def test_unot(self):
  22.         # UNARY_NOT JUMP_IF_FALSE POP_TOP  -->  JUMP_IF_TRUE POP_TOP'
  23.         def unot(x):
  24.             if not x == 2:
  25.                 del x
  26.         asm = disassemble(unot)
  27.         for elem in ('UNARY_NOT', 'JUMP_IF_FALSE'):
  28.             self.assert_(elem not in asm)
  29.         for elem in ('JUMP_IF_TRUE', 'POP_TOP'):
  30.             self.assert_(elem in asm)
  31.  
  32.     def test_elim_inversion_of_is_or_in(self):
  33.         for line, elem in (
  34.             ('not a is b', '(is not)',),
  35.             ('not a in b', '(not in)',),
  36.             ('not a is not b', '(is)',),
  37.             ('not a not in b', '(in)',),
  38.             ):
  39.             asm = dis_single(line)
  40.             self.assert_(elem in asm)
  41.  
  42.     def test_none_as_constant(self):
  43.         # LOAD_GLOBAL None  -->  LOAD_CONST None
  44.         def f(x):
  45.             None
  46.             return x
  47.         asm = disassemble(f)
  48.         for elem in ('LOAD_GLOBAL',):
  49.             self.assert_(elem not in asm)
  50.         for elem in ('LOAD_CONST', '(None)'):
  51.             self.assert_(elem in asm)
  52.         def f():
  53.             'Adding a docstring made this test fail in Py2.5.0'
  54.             return None
  55.         self.assert_('LOAD_CONST' in disassemble(f))
  56.         self.assert_('LOAD_GLOBAL' not in disassemble(f))
  57.  
  58.     def test_while_one(self):
  59.         # Skip over:  LOAD_CONST trueconst  JUMP_IF_FALSE xx  POP_TOP
  60.         def f():
  61.             while 1:
  62.                 pass
  63.             return list
  64.         asm = disassemble(f)
  65.         for elem in ('LOAD_CONST', 'JUMP_IF_FALSE'):
  66.             self.assert_(elem not in asm)
  67.         for elem in ('JUMP_ABSOLUTE',):
  68.             self.assert_(elem in asm)
  69.  
  70.     def test_pack_unpack(self):
  71.         for line, elem in (
  72.             ('a, = a,', 'LOAD_CONST',),
  73.             ('a, b = a, b', 'ROT_TWO',),
  74.             ('a, b, c = a, b, c', 'ROT_THREE',),
  75.             ):
  76.             asm = dis_single(line)
  77.             self.assert_(elem in asm)
  78.             self.assert_('BUILD_TUPLE' not in asm)
  79.             self.assert_('UNPACK_TUPLE' not in asm)
  80.  
  81.     def test_folding_of_tuples_of_constants(self):
  82.         for line, elem in (
  83.             ('a = 1,2,3', '((1, 2, 3))'),
  84.             ('("a","b","c")', "(('a', 'b', 'c'))"),
  85.             ('a,b,c = 1,2,3', '((1, 2, 3))'),
  86.             ('(None, 1, None)', '((None, 1, None))'),
  87.             ('((1, 2), 3, 4)', '(((1, 2), 3, 4))'),
  88.             ):
  89.             asm = dis_single(line)
  90.             self.assert_(elem in asm)
  91.             self.assert_('BUILD_TUPLE' not in asm)
  92.  
  93.         # Bug 1053819:  Tuple of constants misidentified when presented with:
  94.         # . . . opcode_with_arg 100   unary_opcode   BUILD_TUPLE 1  . . .
  95.         # The following would segfault upon compilation
  96.         def crater():
  97.             (~[
  98.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  99.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  100.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  101.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  102.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  103.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  104.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  105.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  106.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  107.                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  108.             ],)
  109.  
  110.     def test_folding_of_binops_on_constants(self):
  111.         for line, elem in (
  112.             ('a = 2+3+4', '(9)'),                   # chained fold
  113.             ('"@"*4', "('@@@@')"),                  # check string ops
  114.             ('a="abc" + "def"', "('abcdef')"),      # check string ops
  115.             ('a = 3**4', '(81)'),                   # binary power
  116.             ('a = 3*4', '(12)'),                    # binary multiply
  117.             ('a = 13//4', '(3)'),                   # binary floor divide
  118.             ('a = 14%4', '(2)'),                    # binary modulo
  119.             ('a = 2+3', '(5)'),                     # binary add
  120.             ('a = 13-4', '(9)'),                    # binary subtract
  121.             ('a = (12,13)[1]', '(13)'),             # binary subscr
  122.             ('a = 13 << 2', '(52)'),                # binary lshift
  123.             ('a = 13 >> 2', '(3)'),                 # binary rshift
  124.             ('a = 13 & 7', '(5)'),                  # binary and
  125.             ('a = 13 ^ 7', '(10)'),                 # binary xor
  126.             ('a = 13 | 7', '(15)'),                 # binary or
  127.             ):
  128.             asm = dis_single(line)
  129.             self.assert_(elem in asm, asm)
  130.             self.assert_('BINARY_' not in asm)
  131.  
  132.         # Verify that unfoldables are skipped
  133.         asm = dis_single('a=2+"b"')
  134.         self.assert_('(2)' in asm)
  135.         self.assert_("('b')" in asm)
  136.  
  137.         # Verify that large sequences do not result from folding
  138.         asm = dis_single('a="x"*1000')
  139.         self.assert_('(1000)' in asm)
  140.  
  141.     def test_folding_of_unaryops_on_constants(self):
  142.         for line, elem in (
  143.             ('`1`', "('1')"),                       # unary convert
  144.             ('-0.5', '(-0.5)'),                     # unary negative
  145.             ('~-2', '(1)'),                         # unary invert
  146.         ):
  147.             asm = dis_single(line)
  148.             self.assert_(elem in asm, asm)
  149.             self.assert_('UNARY_' not in asm)
  150.  
  151.         # Verify that unfoldables are skipped
  152.         for line, elem in (
  153.             ('-"abc"', "('abc')"),                  # unary negative
  154.             ('~"abc"', "('abc')"),                  # unary invert
  155.         ):
  156.             asm = dis_single(line)
  157.             self.assert_(elem in asm, asm)
  158.             self.assert_('UNARY_' in asm)
  159.  
  160.     def test_elim_extra_return(self):
  161.         # RETURN LOAD_CONST None RETURN  -->  RETURN
  162.         def f(x):
  163.             return x
  164.         asm = disassemble(f)
  165.         self.assert_('LOAD_CONST' not in asm)
  166.         self.assert_('(None)' not in asm)
  167.         self.assertEqual(asm.split().count('RETURN_VALUE'), 1)
  168.  
  169.     def test_elim_jump_to_return(self):
  170.         # JUMP_FORWARD to RETURN -->  RETURN
  171.         def f(cond, true_value, false_value):
  172.             return true_value if cond else false_value
  173.         asm = disassemble(f)
  174.         self.assert_('JUMP_FORWARD' not in asm)
  175.         self.assert_('JUMP_ABSOLUTE' not in asm)
  176.         self.assertEqual(asm.split().count('RETURN_VALUE'), 2)
  177.  
  178.     def test_elim_jump_after_return1(self):
  179.         # Eliminate dead code: jumps immediately after returns can't be reached
  180.         def f(cond1, cond2):
  181.             if cond1: return 1
  182.             if cond2: return 2
  183.             while 1:
  184.                 return 3
  185.             while 1:
  186.                 if cond1: return 4
  187.                 return 5
  188.             return 6
  189.         asm = disassemble(f)
  190.         self.assert_('JUMP_FORWARD' not in asm)
  191.         self.assert_('JUMP_ABSOLUTE' not in asm)
  192.         self.assertEqual(asm.split().count('RETURN_VALUE'), 6)
  193.  
  194.     def test_elim_jump_after_return2(self):
  195.         # Eliminate dead code: jumps immediately after returns can't be reached
  196.         def f(cond1, cond2):
  197.             while 1:
  198.                 if cond1: return 4
  199.         asm = disassemble(f)
  200.         self.assert_('JUMP_FORWARD' not in asm)
  201.         # There should be one jump for the while loop.
  202.         self.assertEqual(asm.split().count('JUMP_ABSOLUTE'), 1)
  203.         self.assertEqual(asm.split().count('RETURN_VALUE'), 2)
  204.  
  205.  
  206. def test_main(verbose=None):
  207.     import sys
  208.     from test import test_support
  209.     test_classes = (TestTranforms,)
  210.     test_support.run_unittest(*test_classes)
  211.  
  212.     # verify reference counting
  213.     if verbose and hasattr(sys, "gettotalrefcount"):
  214.         import gc
  215.         counts = [None] * 5
  216.         for i in xrange(len(counts)):
  217.             test_support.run_unittest(*test_classes)
  218.             gc.collect()
  219.             counts[i] = sys.gettotalrefcount()
  220.         print counts
  221.  
  222. if __name__ == "__main__":
  223.     test_main(verbose=True)
  224.