[pypy-svn] r50129 - pypy/branch/llvmgcroot/pypy/rpython/memory/gctransform
arigo at codespeak.net
arigo at codespeak.net
Wed Dec 26 21:30:53 CET 2007
Author: arigo
Date: Wed Dec 26 21:30:53 2007
New Revision: 50129
Modified:
pypy/branch/llvmgcroot/pypy/rpython/memory/gctransform/llvmgcroot.py
Log:
Sort the array when the program starts,
for faster searches in StackRootIterator.pop().
Modified: pypy/branch/llvmgcroot/pypy/rpython/memory/gctransform/llvmgcroot.py
==============================================================================
--- pypy/branch/llvmgcroot/pypy/rpython/memory/gctransform/llvmgcroot.py (original)
+++ pypy/branch/llvmgcroot/pypy/rpython/memory/gctransform/llvmgcroot.py Wed Dec 26 21:30:53 2007
@@ -42,14 +42,21 @@
# some old objects alive for a bit longer than necessary.
def build_stack_root_iterator(self):
- sizeofaddr = llmemory.sizeof(llmemory.Address)
gcdata = self.gcdata
class StackRootIterator:
_alloc_flavor_ = 'raw'
def setup_root_stack():
- pass
+ # The gcmap table is a list of pairs of pointers:
+ # void *SafePointAddress;
+ # void *Shape;
+ # Here, i.e. when the program starts, we sort it
+ # in-place on the SafePointAddress to allow for more
+ # efficient searches.
+ gcmapstart = llop.llvm_gcmapstart(llmemory.Address)
+ gcmapend = llop.llvm_gcmapend(llmemory.Address)
+ insertion_sort(gcmapstart, gcmapend)
setup_root_stack = staticmethod(setup_root_stack)
need_root_stack = False
@@ -96,6 +103,10 @@
# the frame.
#
callee_frame = self.stack_current
+ if llmemory.cast_adr_to_int(callee_frame) & 1:
+ return False # odd bit set here when the callee_frame
+ # is the frame of main(), i.e. when there
+ # is nothing more for us in the stack.
#
# XXX the details are completely specific to X86!!!
# a picture of the stack may help:
@@ -120,33 +131,28 @@
retaddr = callee_frame.address[1]
#
# try to locate the caller function based on retaddr.
- # XXX this is just a linear scan for now, that's
- # incredibly bad.
#
gcmapstart = llop.llvm_gcmapstart(llmemory.Address)
gcmapend = llop.llvm_gcmapend(llmemory.Address)
- while gcmapstart != gcmapend:
- if gcmapstart.address[0] == retaddr:
- #
- # found! Setup pointers allowing us to
- # parse the caller's frame structure...
- #
- shape = gcmapstart.address[1]
- # XXX assumes that .signed is 32-bit
- framesize = shape.signed[0]
- livecount = shape.signed[1]
- caller_frame = callee_frame + 4 + framesize
- self.stack_current = caller_frame
- self.frame_data_base = callee_frame + 8
- self.remaining_roots_in_current_frame = livecount
- self.liveoffsets = shape + 8
- return True
-
- gcmapstart += 2 * sizeofaddr
-
- # retaddr not found. Assume that this is the system function
- # that called the original entry point, i.e. it's the end of
- # the stack for us
+ item = binary_search(gcmapstart, gcmapend, retaddr)
+ if item.address[0] == retaddr:
+ #
+ # found! Setup pointers allowing us to
+ # parse the caller's frame structure...
+ #
+ shape = item.address[1]
+ # XXX assumes that .signed is 32-bit
+ framesize = shape.signed[0] # odd if it's main()
+ livecount = shape.signed[1]
+ caller_frame = callee_frame + 4 + framesize
+ self.stack_current = caller_frame
+ self.frame_data_base = callee_frame + 8
+ self.remaining_roots_in_current_frame = livecount
+ self.liveoffsets = shape + 8
+ return True
+
+ # retaddr not found!
+ llop.debug_fatalerror(lltype.Void, "cannot find gc roots!")
return False
def next_gcroot_from_current_frame(self):
@@ -158,3 +164,49 @@
return StackRootIterator
+
+
+sizeofaddr = llmemory.sizeof(llmemory.Address)
+arrayitemsize = 2 * sizeofaddr
+
+
+def binary_search(start, end, addr1):
+ """Search for an element in a sorted array.
+
+ The interval from the start address (included) to the end address
+ (excluded) is assumed to be a sorted arrays of pairs (addr1, addr2).
+ This searches for the item with a given addr1 and returns its
+ address.
+ """
+ count = (end - start) // arrayitemsize
+ while count > 1:
+ middleindex = count // 2
+ middle = start + middleindex * arrayitemsize
+ if addr1 < middle.address[0]:
+ count = middleindex
+ else:
+ start = middle
+ count -= middleindex
+ return start
+
+def insertion_sort(start, end):
+ """Sort an array of pairs of addresses.
+
+ 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).
+ """
+ next = start
+ while next < end:
+ # assuming the interval from start (included) to next (excluded)
+ # to be already sorted, move the next element back into the array
+ # until it reaches its proper place.
+ addr1 = next.address[0]
+ addr2 = next.address[1]
+ scan = next
+ while scan > start and addr1 < scan.address[-2]:
+ scan.address[0] = scan.address[-2]
+ scan.address[1] = scan.address[-1]
+ scan -= arrayitemsize
+ scan.address[0] = addr1
+ scan.address[1] = addr2
+ next += arrayitemsize
More information about the Pypy-commit
mailing list