[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