[pypy-svn] r76314 - in pypy/branch/asmgcc-64/pypy/translator/c/gcc: . test

jcreigh at codespeak.net jcreigh at codespeak.net
Thu Jul 22 17:06:47 CEST 2010


Author: jcreigh
Date: Thu Jul 22 17:06:45 2010
New Revision: 76314

Modified:
   pypy/branch/asmgcc-64/pypy/translator/c/gcc/test/test_trackgcroot.py
   pypy/branch/asmgcc-64/pypy/translator/c/gcc/trackgcroot.py
Log:
move (de)compress_callshape, format_location, format_callshape to tracker class; update tests accordingly

Modified: pypy/branch/asmgcc-64/pypy/translator/c/gcc/test/test_trackgcroot.py
==============================================================================
--- pypy/branch/asmgcc-64/pypy/translator/c/gcc/test/test_trackgcroot.py	(original)
+++ pypy/branch/asmgcc-64/pypy/translator/c/gcc/test/test_trackgcroot.py	Thu Jul 22 17:06:45 2010
@@ -1,15 +1,12 @@
 import py
 import sys, re
-from pypy.translator.c.gcc.trackgcroot import format_location
-from pypy.translator.c.gcc.trackgcroot import format_callshape
 from pypy.translator.c.gcc.trackgcroot import LOC_NOWHERE, LOC_REG
 from pypy.translator.c.gcc.trackgcroot import LOC_EBP_PLUS, LOC_EBP_MINUS
 from pypy.translator.c.gcc.trackgcroot import LOC_ESP_PLUS
 from pypy.translator.c.gcc.trackgcroot import ElfAssemblerParser
 from pypy.translator.c.gcc.trackgcroot import DarwinAssemblerParser
-from pypy.translator.c.gcc.trackgcroot import compress_callshape
-from pypy.translator.c.gcc.trackgcroot import decompress_callshape
 from pypy.translator.c.gcc.trackgcroot import PARSERS
+from pypy.translator.c.gcc.trackgcroot import ElfFunctionGcRootTracker32
 from StringIO import StringIO
 import py.test
 
@@ -17,40 +14,39 @@
 
 
 def test_format_location():
-    # FIXME
-    py.test.skip()
-    assert format_location(LOC_NOWHERE) == '?'
-    assert format_location(LOC_REG | (1<<2)) == '%ebx'
-    assert format_location(LOC_REG | (2<<2)) == '%esi'
-    assert format_location(LOC_REG | (3<<2)) == '%edi'
-    assert format_location(LOC_REG | (4<<2)) == '%ebp'
-    assert format_location(LOC_EBP_PLUS + 0) == '(%ebp)'
-    assert format_location(LOC_EBP_PLUS + 4) == '4(%ebp)'
-    assert format_location(LOC_EBP_MINUS + 4) == '-4(%ebp)'
-    assert format_location(LOC_ESP_PLUS + 0) == '(%esp)'
-    assert format_location(LOC_ESP_PLUS + 4) == '4(%esp)'
+    cls = ElfFunctionGcRootTracker32
+    assert cls.format_location(LOC_NOWHERE) == '?'
+    assert cls.format_location(LOC_REG | (1<<2)) == '%ebx'
+    assert cls.format_location(LOC_REG | (2<<2)) == '%esi'
+    assert cls.format_location(LOC_REG | (3<<2)) == '%edi'
+    assert cls.format_location(LOC_REG | (4<<2)) == '%ebp'
+    assert cls.format_location(LOC_EBP_PLUS + 0) == '(%ebp)'
+    assert cls.format_location(LOC_EBP_PLUS + 4) == '4(%ebp)'
+    assert cls.format_location(LOC_EBP_MINUS + 4) == '-4(%ebp)'
+    assert cls.format_location(LOC_ESP_PLUS + 0) == '(%esp)'
+    assert cls.format_location(LOC_ESP_PLUS + 4) == '4(%esp)'
 
 def test_format_callshape():
-    # FIXME
-    py.test.skip()
+    cls = ElfFunctionGcRootTracker32
     expected = ('{4(%ebp) '               # position of the return address
                 '| 8(%ebp), 12(%ebp), 16(%ebp), 20(%ebp) '  # 4 saved regs
                 '| 24(%ebp), 28(%ebp)}')                    # GC roots
-    assert format_callshape((LOC_EBP_PLUS+4,
-                             LOC_EBP_PLUS+8,
-                             LOC_EBP_PLUS+12,
-                             LOC_EBP_PLUS+16,
-                             LOC_EBP_PLUS+20,
-                             LOC_EBP_PLUS+24,
-                             LOC_EBP_PLUS+28)) == expected
+    assert cls.format_callshape((LOC_EBP_PLUS+4,
+                                 LOC_EBP_PLUS+8,
+                                 LOC_EBP_PLUS+12,
+                                 LOC_EBP_PLUS+16,
+                                 LOC_EBP_PLUS+20,
+                                 LOC_EBP_PLUS+24,
+                                 LOC_EBP_PLUS+28)) == expected
 
 def test_compress_callshape():
+    cls = ElfFunctionGcRootTracker32
     shape = (1, 127, 0x1234, 0x5678, 0x234567,
              0x765432, 0x61626364, 0x41424344)
-    bytes = list(compress_callshape(shape))
+    bytes = list(cls.compress_callshape(shape))
     print bytes
     assert len(bytes) == 1+1+2+3+4+4+5+5+1
-    assert decompress_callshape(bytes) == list(shape)
+    assert cls.decompress_callshape(bytes) == list(shape)
 
 def test_find_functions_elf():
     source = """\
@@ -143,7 +139,7 @@
     tabledict = {}
     seen = {}
     for entry in table:
-        print '%s: %s' % (entry[0], format_callshape(PARSERS[format], entry[1]))
+        print '%s: %s' % (entry[0], tracker.format_callshape(entry[1]))
         tabledict[entry[0]] = entry[1]
     # find the ";; expected" lines
     prevline = ""
@@ -156,7 +152,7 @@
             label = prevmatch.group(1)
             assert label in tabledict
             got = tabledict[label]
-            assert format_callshape(PARSERS[format], got) == expected
+            assert tracker.format_callshape(got) == expected
             seen[label] = True
             if format == 'msvc':
                 expectedlines.insert(i-2, 'PUBLIC\t%s\n' % (label,))

Modified: pypy/branch/asmgcc-64/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/asmgcc-64/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/asmgcc-64/pypy/translator/c/gcc/trackgcroot.py	Thu Jul 22 17:06:45 2010
@@ -358,6 +358,55 @@
                 self.lines.insert(call.lineno+1, '\t.globl\t%s\n' % (label,))
         call.global_label = label
 
+    @classmethod
+    def compress_callshape(cls, shape):
+        # For a single shape, this turns the list of integers into a list of
+        # bytes and reverses the order of the entries.  The length is
+        # encoded by inserting a 0 marker after the gc roots coming from
+        # shape[5:] and before the 5 values coming from shape[4] to
+        # shape[0].  In practice it seems that shapes contain many integers
+        # whose value is up to a few thousands, which the algorithm below
+        # compresses down to 2 bytes.  Very small values compress down to a
+        # single byte.
+
+        # Callee-save regs plus ret addr
+        min_size = len(cls.CALLEE_SAVE_REGISTERS) + 1
+
+        assert len(shape) >= min_size
+        shape = list(shape)
+        assert 0 not in shape[min_size:]
+        shape.insert(min_size, 0)
+        result = []
+        for loc in shape:
+            assert loc >= 0
+            flag = 0
+            while loc >= 0x80:
+                result.append(int(loc & 0x7F) | flag)
+                flag = 0x80
+                loc >>= 7
+            result.append(int(loc) | flag)
+        result.reverse()
+        return result
+
+    @classmethod
+    def decompress_callshape(cls, bytes):
+        # For tests.  This logic is copied in asmgcroot.py.
+        result = []
+        n = 0
+        while n < len(bytes):
+            value = 0
+            while True:
+                b = bytes[n]
+                n += 1
+                value += b
+                if b < 0x80:
+                    break
+                value = (value - 0x80) << 7
+            result.append(value)
+        result.reverse()
+        assert result[5] == 0
+        del result[5]
+        return result
     # ____________________________________________________________
 
     CANNOT_COLLECT = {    # some of the most used functions that cannot collect
@@ -733,6 +782,64 @@
             if target in ['__alldiv', '__allrem', '__allmul', '__alldvrm']:
                 insns.append(InsnStackAdjust(16))
         return insns
+    # __________ debugging output __________
+
+    @classmethod
+    def format_location(cls, loc):
+        # A 'location' is a single number describing where a value is stored
+        # across a call.  It can be in one of the CALLEE_SAVE_REGISTERS, or
+        # in the stack frame at an address relative to either %esp or %ebp.
+        # The last two bits of the location number are used to tell the cases
+        # apart; see format_location().
+        assert loc >= 0
+        kind = loc & LOC_MASK
+        if kind == LOC_REG:
+            if loc == LOC_NOWHERE:
+                return '?'
+            reg = (loc >> 2) - 1
+            return '%' + cls.CALLEE_SAVE_REGISTERS[reg].replace("%", "")
+        else:
+            offset = loc & ~ LOC_MASK
+            if kind == LOC_EBP_PLUS:
+                result = '(%' + cls.EBP.replace("%", "") + ')'
+            elif kind == LOC_EBP_MINUS:
+                result = '(%' + cls.EBP.replace("%", "") + ')'
+                offset = -offset
+            elif kind == LOC_ESP_PLUS:
+                result = '(%' + cls.ESP.replace("%", "") + ')'
+            else:
+                assert 0, kind
+            if offset != 0:
+                result = str(offset) + result
+            return result
+
+    @classmethod
+    def format_callshape(cls, shape):
+        # A 'call shape' is a tuple of locations in the sense of
+        # format_location().  They describe where in a function frame
+        # interesting values are stored, when this function executes a 'call'
+        # instruction.
+        #
+        #   shape[0]    is the location that stores the fn's own return
+        #               address (not the return address for the currently
+        #               executing 'call')
+        #
+        #   shape[1..N] is where the fn saved its own caller's value of a
+        #               certain callee save register. (where N is the number
+        #               of callee save registers.)
+        #
+        #   shape[>N]   are GC roots: where the fn has put its local GCPTR
+        #               vars
+        #
+        num_callee_save_regs = len(cls.CALLEE_SAVE_REGISTERS)
+        assert isinstance(shape, tuple)
+        # + 1 for the return address
+        assert len(shape) >= (num_callee_save_regs + 1)
+        result = [cls.format_location(loc) for loc in shape]
+        return '{%s | %s | %s}' % (result[0],
+                                   ', '.join(result[1:(num_callee_save_regs+1)]),
+                                   ', '.join(result[(num_callee_save_regs+1):]))
+
 
 class FunctionGcRootTracker32(FunctionGcRootTracker):
     WORD = 4
@@ -1179,7 +1286,7 @@
         table = tracker.computegcmaptable(self.verbose)
         if self.verbose > 1:
             for label, state in table:
-                print >> sys.stderr, label, '\t', format_callshape(self, state)
+                print >> sys.stderr, label, '\t', tracker.format_callshape(state)
         table = compress_gcmaptable(table)
         if self.shuffle and random.random() < 0.5:
             self.gcmaptable[:0] = table
@@ -1432,6 +1539,8 @@
         else:
             word_decl = '.long'
 
+        tracker_cls = PARSERS[self.format].FunctionGcRootTracker
+
         # The pypy_asm_stackwalk() function
 
         if self.format == 'msvc':
@@ -1601,7 +1710,7 @@
                     n = shapes[state]
                 except KeyError:
                     n = shapes[state] = shapeofs
-                    bytes = [str(b) for b in compress_callshape(state)]
+                    bytes = [str(b) for b in tracker_cls.compress_callshape(state)]
                     shapelines.append('\t%s,\t/* %s */\n' % (
                             ', '.join(bytes),
                             shapeofs))
@@ -1633,7 +1742,7 @@
                     n = shapes[state]
                 except KeyError:
                     n = shapes[state] = shapeofs
-                    bytes = [str(b) for b in compress_callshape(state)]
+                    bytes = [str(b) for b in tracker_cls.compress_callshape(state)]
                     shapelines.append('\t/*%d*/\t.byte\t%s\n' % (
                         shapeofs,
                         ', '.join(bytes)))
@@ -1643,7 +1752,7 @@
                 print >> output, '\t%s\t%s-%d' % (
                     word_decl,
                     label,
-                    PARSERS[self.format].FunctionGcRootTracker.OFFSET_LABELS)
+                    tracker_cls.OFFSET_LABELS)
                 print >> output, '\t%s\t%d' % (word_decl, n)
 
             print >> output, """\
@@ -1685,59 +1794,6 @@
     pass
 
 
-# __________ debugging output __________
-
-def format_location(parser, loc):
-    # A 'location' is a single number describing where a value is stored
-    # across a call.  It can be in one of the CALLEE_SAVE_REGISTERS, or
-    # in the stack frame at an address relative to either %esp or %ebp.
-    # The last two bits of the location number are used to tell the cases
-    # apart; see format_location().
-    tracker_cls = parser.FunctionGcRootTracker
-    assert loc >= 0
-    kind = loc & LOC_MASK
-    if kind == LOC_REG:
-        if loc == LOC_NOWHERE:
-            return '?'
-        reg = (loc >> 2) - 1
-        return '%' + tracker_cls.CALLEE_SAVE_REGISTERS[reg].replace("%", "")
-    else:
-        offset = loc & ~ LOC_MASK
-        if kind == LOC_EBP_PLUS:
-            result = '(%' + tracker_cls.EBP.replace("%", "") + ')'
-        elif kind == LOC_EBP_MINUS:
-            result = '(%' + tracker_cls.EBP.replace("%", "") + ')'
-            offset = -offset
-        elif kind == LOC_ESP_PLUS:
-            result = '(%' + tracker_cls.ESP.replace("%", "") + ')'
-        else:
-            assert 0, kind
-        if offset != 0:
-            result = str(offset) + result
-        return result
-
-def format_callshape(parser, shape):
-    # A 'call shape' is a tuple of locations in the sense of format_location().
-    # They describe where in a function frame interesting values are stored,
-    # when this function executes a 'call' instruction.
-    #
-    #   shape[0] is the location that stores the fn's own return address
-    #            (not the return address for the currently executing 'call')
-    #   shape[1] is where the fn saved its own caller's %ebx value
-    #   shape[2] is where the fn saved its own caller's %esi value
-    #   shape[3] is where the fn saved its own caller's %edi value
-    #   shape[4] is where the fn saved its own caller's %ebp value
-    #   shape[>=5] are GC roots: where the fn has put its local GCPTR vars
-    #
-    num_callee_save_regs = len(parser.FunctionGcRootTracker.CALLEE_SAVE_REGISTERS)
-    assert isinstance(shape, tuple)
-    # + 1 for the return address
-    assert len(shape) >= (num_callee_save_regs + 1)
-    result = [format_location(parser, loc) for loc in shape]
-    return '{%s | %s | %s}' % (result[0],
-                               ', '.join(result[1:(num_callee_save_regs+1)]),
-                               ', '.join(result[(num_callee_save_regs+1):]))
-
 # __________ table compression __________
 
 def compress_gcmaptable(table):
@@ -1764,54 +1820,6 @@
         yield (label1, state, is_range)
         i = j
 
-def compress_callshape(shape):
-    # For a single shape, this turns the list of integers into a list of
-    # bytes and reverses the order of the entries.  The length is
-    # encoded by inserting a 0 marker after the gc roots coming from
-    # shape[5:] and before the 5 values coming from shape[4] to
-    # shape[0].  In practice it seems that shapes contain many integers
-    # whose value is up to a few thousands, which the algorithm below
-    # compresses down to 2 bytes.  Very small values compress down to a
-    # single byte.
-
-    # FIXME
-    # MIN_SIZE = 5
-    MIN_SIZE = 7
-
-    assert len(shape) >= MIN_SIZE
-    shape = list(shape)
-    assert 0 not in shape[MIN_SIZE:]
-    shape.insert(MIN_SIZE, 0)
-    result = []
-    for loc in shape:
-        assert loc >= 0
-        flag = 0
-        while loc >= 0x80:
-            result.append(int(loc & 0x7F) | flag)
-            flag = 0x80
-            loc >>= 7
-        result.append(int(loc) | flag)
-    result.reverse()
-    return result
-
-def decompress_callshape(bytes):
-    # For tests.  This logic is copied in asmgcroot.py.
-    result = []
-    n = 0
-    while n < len(bytes):
-        value = 0
-        while True:
-            b = bytes[n]
-            n += 1
-            value += b
-            if b < 0x80:
-                break
-            value = (value - 0x80) << 7
-        result.append(value)
-    result.reverse()
-    assert result[5] == 0
-    del result[5]
-    return result
 
 def getidentifier(s):
     def mapchar(c):



More information about the Pypy-commit mailing list