[pypy-svn] r51374 - in pypy/dist/pypy: rpython/lltypesystem rpython/memory/gctransform translator/c/gcc translator/c/gcc/test translator/c/src
arigo at codespeak.net
arigo at codespeak.net
Sun Feb 10 18:44:06 CET 2008
Author: arigo
Date: Sun Feb 10 18:44:01 2008
New Revision: 51374
Modified:
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py
pypy/dist/pypy/translator/c/gcc/test/test_trackgcroot.py
pypy/dist/pypy/translator/c/gcc/trackgcroot.py
pypy/dist/pypy/translator/c/src/mem.h
Log:
Revert r51371 for now. Either it causes a rare "cannot find gc roots!"
condition, or it's just because the working copy I compiled this
pypy-c-asmgcc-faassen from was not completely up-to-date. We'll see.
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sun Feb 10 18:44:01 2008
@@ -412,7 +412,6 @@
'llvm_frameaddress': LLOp(sideeffects=False),
'llvm_gcmapstart': LLOp(sideeffects=False),
'llvm_gcmapend': LLOp(sideeffects=False),
- 'llvm_gccallshapes': LLOp(sideeffects=False),
'llvm_store_gcroot': LLOp(),
'llvm_load_gcroot': LLOp(),
Modified: pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/asmgcroot.py Sun Feb 10 18:44:01 2008
@@ -50,12 +50,11 @@
def _asm_callback(initialframedata):
self.walk_stack_from(initialframedata)
self._asm_callback = _asm_callback
- self._shape_decompressor = ShapeDecompressor()
def setup_root_walker(self):
- # The gcmap table is a list of entries, two machine words each:
+ # The gcmap table is a list of pairs of pointers:
# void *SafePointAddress;
- # int Shape;
+ # void *Shape;
# Here, i.e. when the program starts, we sort it
# in-place on the SafePointAddress to allow for more
# efficient searches.
@@ -99,9 +98,9 @@
callback from the GC code for each GC root found in 'caller'.
"""
#
- # The gcmap table is a list of entries, two machine words each:
+ # The gcmap table is a list of pairs of pointers:
# void *SafePointAddress;
- # int Shape;
+ # void *Shape;
#
# A "safe point" is the return address of a call.
# The "shape" of a safe point is a list of integers
@@ -149,26 +148,20 @@
gcmapend = llop.llvm_gcmapend(llmemory.Address)
item = binary_search(gcmapstart, gcmapend, retaddr)
if item.address[0] != retaddr:
- # 'retaddr' not exactly found. Check that 'item' the start of a
- # compressed range containing 'retaddr'.
- if retaddr > item.address[0] and item.signed[1] < 0:
- pass # ok
- else:
- llop.debug_fatalerror(lltype.Void, "cannot find gc roots!")
- return False
+ # retaddr not found!
+ llop.debug_fatalerror(lltype.Void, "cannot find gc roots!")
+ return False
#
# found! Enumerate the GC roots in the caller frame
#
- shape = item.signed[1]
- if shape < 0:
- shape = ~ shape # can ignore this "range" marker here
- self._shape_decompressor.setpos(shape)
+ shape = item.address[1]
collect_stack_root = self.gcdata._gc_collect_stack_root
gc = self.gc
- while True:
- location = self._shape_decompressor.next()
- if location == 0:
- break
+ LIVELOCS = 1 + CALLEE_SAVED_REGS + 1 # index of the first gc root loc
+ livecount = shape.signed[LIVELOCS-1]
+ while livecount > 0:
+ livecount -= 1
+ location = shape.signed[LIVELOCS + livecount]
addr = self.getlocation(callee, location)
if addr.address[0] != llmemory.NULL:
collect_stack_root(gc, addr)
@@ -176,18 +169,17 @@
# track where the caller_frame saved the registers from its own
# caller
#
- reg = CALLEE_SAVED_REGS - 1
- while reg >= 0:
- location = self._shape_decompressor.next()
+ location = shape.signed[0]
+ caller.frame_address = self.getlocation(callee, location)
+ if not caller.frame_address: # marker that means "I'm the frame
+ return False # of the entry point, stop walking"
+ reg = 0
+ while reg < CALLEE_SAVED_REGS:
+ location = shape.signed[1+reg]
addr = self.getlocation(callee, location)
caller.regs_stored_at[reg] = addr
- reg -= 1
-
- location = self._shape_decompressor.next()
- caller.frame_address = self.getlocation(callee, location)
- # we get a NULL marker to mean "I'm the frame
- # of the entry point, stop walking"
- return caller.frame_address != llmemory.NULL
+ reg += 1
+ return True
def getlocation(self, callee, location):
"""Get the location in the 'caller' frame of a variable, based
@@ -249,9 +241,6 @@
This is an insertion sort, so it's slowish unless the array is mostly
sorted already (which is what I expect, but XXX check this).
"""
- # XXX this should check that it's not changing the relative order
- # of entry and the following entry in case it's a compressed "range"
- # entry, i.e. "entry.signed[1] < 0".
next = start
while next < end:
# assuming the interval from start (included) to next (excluded)
@@ -270,31 +259,6 @@
# ____________________________________________________________
-class ShapeDecompressor:
- _alloc_flavor_ = "raw"
-
- def setpos(self, pos):
- gccallshapes = llop.llvm_gccallshapes(llmemory.Address)
- self.addr = gccallshapes + pos
-
- def next(self):
- value = 0
- addr = self.addr
- while True:
- b = ord(addr.char[0])
- addr += 1
- value += b
- if b < 0x80:
- break
- value = (value - 0x80) << 7
- self.addr = addr
- if value & 1:
- value = ~ value
- value = value >> 1
- return value
-
-# ____________________________________________________________
-
#
# The special pypy_asm_stackwalk(), implemented directly in
# assembler, fills information about the current stack top in an
Modified: pypy/dist/pypy/translator/c/gcc/test/test_trackgcroot.py
==============================================================================
--- pypy/dist/pypy/translator/c/gcc/test/test_trackgcroot.py (original)
+++ pypy/dist/pypy/translator/c/gcc/test/test_trackgcroot.py Sun Feb 10 18:44:01 2008
@@ -6,8 +6,6 @@
from pypy.translator.c.gcc.trackgcroot import LOC_EBP_BASED, LOC_ESP_BASED
from pypy.translator.c.gcc.trackgcroot import GcRootTracker
from pypy.translator.c.gcc.trackgcroot import FunctionGcRootTracker
-from pypy.translator.c.gcc.trackgcroot import compress_callshape
-from pypy.translator.c.gcc.trackgcroot import decompress_callshape
from StringIO import StringIO
this_dir = py.path.local(__file__).dirpath()
@@ -38,14 +36,6 @@
LOC_EBP_BASED+24,
LOC_EBP_BASED+28)) == expected
-def test_compress_callshape():
- shape = (1, -3, 0x1234, -0x5678, 0x234567,
- -0x765432, 0x61626364, -0x41424344)
- bytes = list(compress_callshape(shape))
- print bytes
- assert len(bytes) == 1+1+2+3+4+4+5+5+1
- assert decompress_callshape(bytes) == list(shape)
-
def test_find_functions():
source = """\
\t.p2align 4,,15
Modified: pypy/dist/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/dist/pypy/translator/c/gcc/trackgcroot.py (original)
+++ pypy/dist/pypy/translator/c/gcc/trackgcroot.py Sun Feb 10 18:44:01 2008
@@ -35,8 +35,6 @@
def dump(self, output):
assert self.seen_main
shapes = {}
- shapelines = []
- shapeofs = 0
print >> output, """\t.text
.globl pypy_asm_stackwalk
.type pypy_asm_stackwalk, @function
@@ -70,26 +68,30 @@
print >> output, '\t.align\t4'
print >> output, '\t.globl\t__gcmapstart'
print >> output, '__gcmapstart:'
- for label, state, is_range in self.gcmaptable:
- try:
- n = shapes[state]
- except KeyError:
- n = shapes[state] = shapeofs
- bytes = [str(b) for b in compress_callshape(state)]
- shapelines.append('\t/*%d*/\t.byte\t%s\n' % (
- shapeofs,
- ', '.join(bytes)))
- shapeofs += len(bytes)
- if is_range:
- n = ~ n
+ for label, state in self.gcmaptable:
+ if state not in shapes:
+ lst = ['__gcmap_shape']
+ for n in state:
+ if n < 0:
+ n = 'm%d' % (-n,)
+ lst.append(str(n))
+ shapes[state] = '_'.join(lst)
print >> output, '\t.long\t%s' % (label,)
- print >> output, '\t.long\t%d' % (n,)
+ print >> output, '\t.long\t%s' % (shapes[state],)
print >> output, '\t.globl\t__gcmapend'
print >> output, '__gcmapend:'
print >> output, '\t.section\t.rodata'
- print >> output, '\t.globl\t__gccallshapes'
- print >> output, '__gccallshapes:'
- output.writelines(shapelines)
+ print >> output, '\t.align\t4'
+ keys = shapes.keys()
+ keys.sort()
+ FIXED = 1 + len(CALLEE_SAVE_REGISTERS)
+ for state in keys:
+ print >> output, '%s:' % (shapes[state],)
+ for i in range(FIXED):
+ print >> output, '\t.long\t%d' % (state[i],)
+ print >> output, '\t.long\t%d' % (len(state)-FIXED,)
+ for p in state[FIXED:]:
+ print >> output, '\t.long\t%d' % (p,) # gcroots
def find_functions(self, iterlines):
functionlines = []
@@ -113,13 +115,10 @@
yield False, functionlines
def process(self, iterlines, newfile, entrypoint='main', filename='?'):
- self.localgcmaptable = []
for in_function, lines in self.find_functions(iterlines):
if in_function:
lines = self.process_function(lines, entrypoint, filename)
newfile.writelines(lines)
- self.gcmaptable.extend(compress_gcmaptable(self.localgcmaptable))
- del self.localgcmaptable
self.files_seen += 1
def process_function(self, lines, entrypoint, filename):
@@ -132,7 +131,7 @@
if self.verbose > 1:
for label, state in table:
print >> sys.stderr, label, '\t', format_callshape(state)
- self.localgcmaptable.extend(table)
+ self.gcmaptable.extend(table)
self.seen_main |= tracker.is_main
return tracker.lines
@@ -898,82 +897,6 @@
', '.join(result[1:5]),
', '.join(result[5:]))
-# __________ table compression __________
-
-def compress_gcmaptable(table):
- # Compress ranges table[i:j] of entries with the same state
- # into a single entry whose label is the start of the range.
- # The last element in the table is never compressed in this
- # way for debugging reasons, to avoid that a random address
- # in memory gets mapped to the last element in the table
- # just because it's the closest address.
- # Also, compress_gcmaptable() should be called after each
- # .s file processed -- otherwise the result depends on the
- # linker not rearranging the .s files in memory, which looks
- # fragile.
- i = 0
- limit = len(table) - 1 # only process entries table[:limit]
- while i < len(table):
- label1, state = table[i]
- is_range = False
- j = i + 1
- while j < limit and table[j][1] == state:
- is_range = True
- j += 1
- # now all entries in table[i:j] have the same state
- 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.
- assert len(shape) >= 5
- shape = list(shape)
- assert 0 not in shape[5:]
- shape.insert(5, 0)
- result = []
- for loc in shape:
- if loc < 0:
- loc = (-loc) * 2 - 1
- else:
- loc = loc * 2
- 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
- if value & 1:
- value = ~ value
- value = value >> 1
- result.append(value)
- result.reverse()
- assert result[5] == 0
- del result[5]
- return result
-
if __name__ == '__main__':
if sys.argv and sys.argv[1] == '-v':
Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h (original)
+++ pypy/dist/pypy/translator/c/src/mem.h Sun Feb 10 18:44:01 2008
@@ -10,7 +10,7 @@
extern char __gcmapstart;
extern char __gcmapend;
-extern char __gccallshapes;
+extern char* __gcmap_frame_address(void);
#define PYPY_GCROOT(p) asm ("/* GCROOT %0 */" : "=g" (p) : "0" (p) : "memory")
#define pypy_asm_gcroot(p) ({void*_r; \
@@ -19,7 +19,10 @@
#define OP_LLVM_GCMAPSTART(r) r = &__gcmapstart
#define OP_LLVM_GCMAPEND(r) r = &__gcmapend
-#define OP_LLVM_GCCALLSHAPES(r) r = &__gccallshapes
+#define OP_LLVM_FRAMEADDRESS(r) asm ("pypygetframeaddress %0" : "=r" (r))
+/* NB. we cannot use __builtin_frame_address(0) - apparently, gcc thinks
+ it can return %ebp even if -fomit-frame-pointer is specified, which
+ doesn't work. So we need a bit of help from trackgcroot.py... */
#define RAW_MALLOC_ZERO_FILLED 0
More information about the Pypy-commit
mailing list