[pypy-commit] pypy tealet: Tweak delegation between rtealet.py and the GC. It seems that the

arigo noreply at buildbot.pypy.org
Wed Jul 6 20:28:45 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: tealet
Changeset: r45383:01a6ac124f45
Date: 2011-06-12 15:53 +0200
http://bitbucket.org/pypy/pypy/changeset/01a6ac124f45/

Log:	Tweak delegation between rtealet.py and the GC. It seems that the
	GC needs to do a bit more, but it's not really more code in total.

diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -32,6 +32,7 @@
                default=False, cmdline="--tealet",
                requires=[("translation.type_system", "lltype"),
                          ("translation.gctransformer", "framework"),
+                         ("translation.gcrootfinder", "shadowstack"),
                          ("translation.thread", False)]),    # XXX temporary
     ChoiceOption("type_system", "Type system to use when RTyping",
                  ["lltype", "ootype"], cmdline=None, default="lltype",
diff --git a/pypy/rlib/_tealet_rffi.py b/pypy/rlib/_tealet_rffi.py
--- a/pypy/rlib/_tealet_rffi.py
+++ b/pypy/rlib/_tealet_rffi.py
@@ -11,8 +11,7 @@
 def llexternal(funcname, args, restype):
     return rffi.llexternal(funcname, args, restype,
                            compilation_info=eci,
-                           sandboxsafe=True, threadsafe=False,
-                           _nowrapper=True)
+                           sandboxsafe=True, _nowrapper=True)
 
 TEALET_P = rffi.COpaquePtr('tealet_t', compilation_info=eci)
 TEALET_RUN_P = lltype.Ptr(lltype.FuncType([TEALET_P, rffi.VOIDP], TEALET_P))
diff --git a/pypy/rlib/rtealet.py b/pypy/rlib/rtealet.py
--- a/pypy/rlib/rtealet.py
+++ b/pypy/rlib/rtealet.py
@@ -22,7 +22,6 @@
 
     class Tealet(base_class):
         lltealet = _tealet_rffi.NULL_TEALET
-        _ll_saved_stack = None
 
         def switch(self):
             _switch(self)
@@ -58,8 +57,6 @@
 class Switcher(object):
     current = None
     target = None
-    count_roots = 0
-    lst = None
     exception = None
 switcher = Switcher()
 
@@ -143,52 +140,37 @@
         raise e
 
 # ____________________________________________________________
+#
+# Shadow stack saving/restoring.
 
-ROOT_WALKER = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
+GCPTR_ARRAY  = lltype.Ptr(lltype.GcArray(llmemory.GCREF))
+SIGNED_ARRAY = lltype.Ptr(lltype.GcArray(lltype.Signed))
+WALKER_PTR   = lltype.Ptr(lltype.Struct('walker',
+                                        ('gcptr_array', GCPTR_ARRAY),
+                                        ('signed_array', SIGNED_ARRAY)))
+walker = lltype.malloc(WALKER_PTR.TO, immortal=True)
 
-def _count_roots_walker(root):
-    switcher.count_roots += 1
-
-def _save_root_walker(root):
-    i = switcher.count_roots
-    switcher.count_roots = i + 1
-    gcobj = llmemory.cast_adr_to_ptr(root.address[0], llmemory.GCREF)
-    switcher.lst[i] = gcobj
+Tealet._gc_gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
+Tealet._gc_signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
 
 def _save_shadow_stack():
-    switcher.count_roots = 0
-    fn = llhelper(ROOT_WALKER, _count_roots_walker)
-    llop.gc_walk_stack_roots(lltype.Void, fn)
-    n = switcher.count_roots
-    #
+    llop.gc_save_stack_roots(lltype.Void, walker)
     tealet = switcher.current
-    ll_assert(tealet._ll_saved_stack is None, "tealet stack mismatch (save)")
-    tealet._ll_saved_stack = [lltype.nullptr(llmemory.GCREF.TO)] * n
-    switcher.count_roots = 0
-    switcher.lst = tealet._ll_saved_stack
-    fn = llhelper(ROOT_WALKER, _save_root_walker)
-    llop.gc_walk_stack_roots(lltype.Void, fn)
-    ll_assert(n == switcher.count_roots, "tealet stack mismatch (count1)")
-    switcher.lst = None
+    ll_assert(not tealet._gc_gcptr_array, "tealet stack mismatch (save)")
+    tealet._gc_gcptr_array  = walker.gcptr_array
+    tealet._gc_signed_array = walker.signed_array
+    walker.gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
+    walker.signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
 _save_shadow_stack._dont_inline_ = True
 
-def _restore_root_walker(root):
-    i = switcher.count_roots
-    switcher.count_roots = i + 1
-    gcobj = switcher.lst[i]
-    root.address[0] = llmemory.cast_ptr_to_adr(gcobj)
-
 def _restore_shadow_stack():
     tealet = switcher.target
-    lst = tealet._ll_saved_stack
-    ll_assert(lst is not None, "tealet stack mismatch (restore)")
-    tealet._ll_saved_stack = None
-    switcher.count_roots = 0
-    switcher.lst = lst
-    n = len(lst)
-    fn = llhelper(ROOT_WALKER, _restore_root_walker)
-    llop.gc_set_stack_roots_count(lltype.Void, n)
-    llop.gc_walk_stack_roots(lltype.Void, fn)
-    ll_assert(n == switcher.count_roots, "tealet stack mismatch (count2)")
-    switcher.lst = None
+    ll_assert(bool(tealet._gc_gcptr_array), "tealet stack mismatch (restore)")
+    walker.gcptr_array  = tealet._gc_gcptr_array
+    walker.signed_array = tealet._gc_signed_array
+    tealet._gc_gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
+    tealet._gc_signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
+    llop.gc_restore_stack_roots(lltype.Void, walker)
+    walker.gcptr_array  = lltype.nullptr(GCPTR_ARRAY.TO)
+    walker.signed_array = lltype.nullptr(SIGNED_ARRAY.TO)
 _restore_shadow_stack._dont_inline_ = True
diff --git a/pypy/rlib/test/test_rtealet.py b/pypy/rlib/test/test_rtealet.py
--- a/pypy/rlib/test/test_rtealet.py
+++ b/pypy/rlib/test/test_rtealet.py
@@ -1,3 +1,4 @@
+import py
 from pypy.translator.c.test.test_standalone import StandaloneTests
 
 
@@ -28,3 +29,5 @@
 
 class TestTealetAsmgcc(BaseTestTealet):
     gcrootfinder = "asmgcc"
+    def setup_class(cls):
+        py.test.skip("XXX in-progress")
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -483,8 +483,8 @@
     'gc_dump_rpy_heap'    : LLOp(),
     'gc_typeids_z'        : LLOp(),
 
-    'gc_walk_stack_roots' : LLOp(),        # for tealet support
-    'gc_set_stack_roots_count': LLOp(),    #        "
+    'gc_save_stack_roots'   : LLOp(),        # for tealet support
+    'gc_restore_stack_roots': LLOp(),        # for tealet support
 
     # ------- JIT & GC interaction, only for some GCs ----------
 
diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py
--- a/pypy/rpython/memory/gctransform/framework.py
+++ b/pypy/rpython/memory/gctransform/framework.py
@@ -1006,22 +1006,21 @@
             hop.genop("direct_call", [self.root_walker.thread_after_fork_ptr]
                                      + hop.spaceop.args)
 
-    def gct_gc_walk_stack_roots(self, hop):
+    def gct_gc_save_stack_roots(self, hop):
         # only available if tealet support is enabled
         assert self.translator.config.translation.tealet
         # no gc root in the stack around such an llop!
         assert not self.push_roots(hop)
-        hop.genop("direct_call", [self.root_walker.ll_walk_stack_roots_ptr]
+        hop.genop("direct_call", [self.root_walker.ll_save_stack_roots_ptr]
                                  + hop.spaceop.args)
 
-    def gct_gc_set_stack_roots_count(self, hop):
+    def gct_gc_restore_stack_roots(self, hop):
+        # only available if tealet support is enabled
         assert self.translator.config.translation.tealet
         # no gc root in the stack around such an llop!
         assert not self.push_roots(hop)
-        if hasattr(self.root_walker, 'set_stack_roots_count_ptr'):
-            hop.genop("direct_call",
-                      [self.root_walker.set_stack_roots_count_ptr]
-                      + hop.spaceop.args)
+        hop.genop("direct_call", [self.root_walker.ll_restore_stack_roots_ptr]
+                                 + hop.spaceop.args)
 
     def gct_gc_get_type_info_group(self, hop):
         return hop.cast_result(self.c_type_info_group)
@@ -1347,20 +1346,8 @@
             self.__class__.__name__,))
 
     def need_tealet_support(self, gctransformer, getfn):
-        #
-        def ll_walk_stack_roots(fnptr_stack_root):
-            gcdata = self.gcdata
-            gcdata._fnptr_stack_root = fnptr_stack_root
-            self.walk_stack_roots(_ll_collect)
-        #
-        def _ll_collect(gc, root):
-            gcdata = self.gcdata
-            gcdata._fnptr_stack_root(root)
-        #
-        FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
-        s_FuncPtr = annmodel.SomePtr(FUNCPTR)
-        self.ll_walk_stack_roots_ptr = getfn(ll_walk_stack_roots,
-                                             [s_FuncPtr], annmodel.s_None)
+        raise Exception("%s does not support tealets" % (
+            self.__class__.__name__,))
 
 
 class ShadowStackRootWalker(BaseRootWalker):
@@ -1424,34 +1411,45 @@
 
     def need_tealet_support(self, gctransformer, getfn):
         assert not gctransformer.translator.config.translation.jit, (
-            "not supported yet: jit + shadowstack + tealet")
+            "XXX in-progress: tealet + jit + shadowstack")
         assert not gctransformer.translator.config.translation.thread, (
-            "not supported yet: thread + shadowstack + tealet")
+            "XXX check me: tealet + thread + shadowstack")
         #
-        # We need a custom version of ll_walk_stack_roots because the issue
-        # is that when we try to restore the shadowstack, it initially
-        # contains garbage; and the default ll_walk_stack_roots would skip
-        # the NULL pointers in it.
+        GCPTR_ARRAY  = lltype.Ptr(lltype.GcArray(llmemory.GCREF))
+        SIGNED_ARRAY = lltype.Ptr(lltype.GcArray(lltype.Signed))
+        WALKER_PTR   = lltype.Ptr(lltype.Struct('walker',
+                           ('gcptr_array', GCPTR_ARRAY),
+                           ('signed_array', SIGNED_ARRAY)))
         gcdata = self.gcdata
         #
-        def ll_walk_stack_roots(fnptr_stack_root):
+        def ll_save_stack_roots(walker):
             addr = gcdata.root_stack_base
             end = gcdata.root_stack_top
-            while addr != end:
-                fnptr_stack_root(addr)
-                addr += sizeofaddr
+            count = (end - addr) // sizeofaddr
+            walker.gcptr_array = array = lltype.malloc(GCPTR_ARRAY.TO, count)
+            n = 0
+            while n < len(array):
+                array[n] = llmemory.cast_adr_to_ptr(addr.address[n],
+                                                    llmemory.GCREF)
+                n += 1
         #
-        FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Void))
-        s_FuncPtr = annmodel.SomePtr(FUNCPTR)
-        self.ll_walk_stack_roots_ptr = getfn(ll_walk_stack_roots,
-                                             [s_FuncPtr], annmodel.s_None)
+        def ll_restore_stack_roots(walker):
+            array = walker.gcptr_array
+            addr = gcdata.root_stack_base
+            gcdata.root_stack_top = addr + len(array) * sizeofaddr
+            n = 0
+            while n < len(array):
+                addr.address[n] = llmemory.cast_ptr_to_adr(array[n])
+                n += 1
         #
-        def set_stack_roots_count(count):
-            bytes = count * llmemory.sizeof(llmemory.Address)
-            gcdata.root_stack_top = gcdata.root_stack_base + bytes
-        self.set_stack_roots_count_ptr = getfn(set_stack_roots_count,
-                                               [annmodel.SomeInteger()],
-                                               annmodel.s_None)
+        self.ll_save_stack_roots_ptr = getfn(ll_save_stack_roots,
+                                             [annmodel.SomePtr(WALKER_PTR)],
+                                             annmodel.s_None,
+                                             minimal_transform=False)
+        self.ll_restore_stack_roots_ptr = getfn(ll_restore_stack_roots,
+                                                [annmodel.SomePtr(WALKER_PTR)],
+                                                annmodel.s_None,
+                                                minimal_transform=False)
 
     def need_thread_support(self, gctransformer, getfn):
         from pypy.module.thread import ll_thread    # xxx fish


More information about the pypy-commit mailing list