[pypy-commit] pypy stackroot-speedup: (fijal, arigo)
arigo
noreply at buildbot.pypy.org
Sat Jan 28 16:55:47 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stackroot-speedup
Changeset: r51910:641b24e593c6
Date: 2012-01-28 16:30 +0100
http://bitbucket.org/pypy/pypy/changeset/641b24e593c6/
Log: (fijal, arigo)
Trying to speed up the stack root walking step of minor collections.
The idea is to mark and detect the limit of the previous stack root
walking, so that we don't need to repeat tracing over the already-
scanned, already-old objects.
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -1266,6 +1266,9 @@
def _cast_to_ptr(self, TP):
return force_cast(TP, self.intval)
+ def _cast_to_int(self, symbolic="ignored"):
+ return long(self) # 'self' is already a subclass of long...
+
def __repr__(self):
return '<_lladdress %s>' % (self.void_p,)
diff --git a/pypy/rpython/memory/gctransform/shadowstack.py b/pypy/rpython/memory/gctransform/shadowstack.py
--- a/pypy/rpython/memory/gctransform/shadowstack.py
+++ b/pypy/rpython/memory/gctransform/shadowstack.py
@@ -1,7 +1,7 @@
from pypy.rpython.memory.gctransform.framework import BaseRootWalker
from pypy.rpython.memory.gctransform.framework import sizeofaddr
from pypy.rpython.annlowlevel import llhelper
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rlib.debug import ll_assert
from pypy.rlib.nonconst import NonConstant
from pypy.annotation import model as annmodel
@@ -10,6 +10,11 @@
class ShadowStackRootWalker(BaseRootWalker):
need_root_stack = True
+ # special values in the shadowstack (different values than
+ # the jit's MARKER, which is 8):
+ MARKER_NOT_TRACED = 16
+ MARKER_TRACED = 24
+
def __init__(self, gctransformer):
BaseRootWalker.__init__(self, gctransformer)
# NB. 'self' is frozen, but we can use self.gcdata to store state
@@ -42,12 +47,34 @@
addr += sizeofaddr
self.rootstackhook = jit_walk_stack_root
else:
- def default_walk_stack_root(callback, addr, end):
+ def default_walk_stack_root(callback, start, end, is_minor):
gc = self.gc
- while addr != end:
+ addr = end
+ while addr != start:
+ addr -= sizeofaddr
+ value = llmemory.cast_adr_to_int(addr.address[0])
+ #
+ # If myaddr contains MARKER_TRACED, and if we are doing
+ # a minor collection, then stop here. The previous items
+ # have all been traced at least once already, so they
+ # cannot contain young pointers.
+ if value == self.MARKER_TRACED:
+ if is_minor:
+ break
+ continue # ignore the marker and continue
+ #
+ # If myaddr contains MARKER_NOT_TRACED, replace it by
+ # MARKER_TRACED.
+ if value == self.MARKER_NOT_TRACED:
+ addr.address[0] = rffi.cast(llmemory.Address,
+ self.MARKER_TRACED)
+ continue
+ #
+ # Regular part follows: invoke 'callback' if myaddr really
+ # points to an object
if gc.points_to_valid_gc_object(addr):
callback(gc, addr)
- addr += sizeofaddr
+ #
self.rootstackhook = default_walk_stack_root
self.shadow_stack_pool = ShadowStackPool(gcdata)
diff --git a/pypy/rpython/memory/gctransform/test/test_shadowstack.py b/pypy/rpython/memory/gctransform/test/test_shadowstack.py
new file mode 100644
--- /dev/null
+++ b/pypy/rpython/memory/gctransform/test/test_shadowstack.py
@@ -0,0 +1,54 @@
+from pypy.rpython.memory.gctransform.shadowstack import ShadowStackRootWalker
+from pypy.rpython.memory.gctransform.shadowstack import sizeofaddr
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+
+
+class MockGC:
+ def points_to_valid_gc_object(self, addr):
+ n = rffi.cast(lltype.Signed, addr.address[0])
+ if n > 0x1000:
+ return True
+ if n == 0:
+ return False
+ assert 0, "oups, bogus address: 0x%x" % n
+
+class MockGCData:
+ gc = MockGC()
+
+class MockGcTransformer:
+ gcdata = MockGCData()
+ translator = None
+ root_stack_depth = None
+
+
+def test_default_walk_stack_root():
+ for (minor, already_traced) in [(False, False),
+ (False, True),
+ (True, False),
+ (True, True)]:
+ root_stack_size = sizeofaddr * 5
+ a = llmemory.raw_malloc(root_stack_size)
+ a.address[0] = llmemory.NULL
+ a.address[1] = rffi.cast(llmemory.Address, 0x1234)
+ if already_traced:
+ marker = ShadowStackRootWalker.MARKER_TRACED
+ else:
+ marker = ShadowStackRootWalker.MARKER_NOT_TRACED
+ a.address[2] = rffi.cast(llmemory.Address, marker)
+ a.address[3] = rffi.cast(llmemory.Address, 0x5678)
+ a.address[4] = llmemory.NULL
+ walker = ShadowStackRootWalker(MockGcTransformer())
+ seen = []
+ def callback(gc, addr):
+ assert gc == walker.gc
+ seen.append(rffi.cast(lltype.Signed, addr.address[0]))
+ aend = a + 5 * sizeofaddr
+ walker.rootstackhook(callback, a, aend, is_minor=minor)
+ marker = rffi.cast(lltype.Signed, a.address[2])
+ assert marker == ShadowStackRootWalker.MARKER_TRACED
+ if minor and already_traced:
+ assert seen == [0x5678]
+ else:
+ assert seen == [0x5678, 0x1234]
+ llmemory.raw_free(a)
+
More information about the pypy-commit
mailing list