Author: Armin Rigo <ar...@tunes.org>
Branch: callback-stacklet
Changeset: r64125:43633e9da628
Date: 2013-05-15 13:30 +0200
http://bitbucket.org/pypy/pypy/changeset/43633e9da628/

Log:    in-progress

diff --git a/rpython/memory/gctransform/asmgcroot.py 
b/rpython/memory/gctransform/asmgcroot.py
--- a/rpython/memory/gctransform/asmgcroot.py
+++ b/rpython/memory/gctransform/asmgcroot.py
@@ -172,10 +172,45 @@
         self.gctransformer = gctransformer
 
     def need_stacklet_support(self, gctransformer, getfn):
+        from rpython.annotator import model as annmodel
+        from rpython.rlib import _stacklet_asmgcc
         # stacklet support: BIG HACK for rlib.rstacklet
-        from rpython.rlib import _stacklet_asmgcc
         _stacklet_asmgcc._asmstackrootwalker = self     # as a global! argh
         _stacklet_asmgcc.complete_destrptr(gctransformer)
+        #
+        def gc_detach_callback_pieces():
+            # XXX use belongs_to_current_thread() below
+            anchor = llmemory.cast_ptr_to_adr(gcrootanchor)
+            initialframedata = anchor.address[1]
+            if initialframedata == anchor:
+                return llmemory.NULL            # empty
+            lastframedata = anchor.address[0]
+            lastframedata.address[1] = llmemory.NULL
+            initialframedata.address[0] = llmemory.NULL
+            anchor.address[0] = anchor
+            anchor.address[1] = anchor
+            return initialframedata
+        #
+        def gc_reattach_callback_pieces(pieces):
+            ll_assert(pieces != llmemory.NULL, "should not be called if NULL")
+            ll_assert(pieces.address[0] == llmemory.NULL,
+                      "not a correctly detached stack piece")
+            anchor = llmemory.cast_ptr_to_adr(gcrootanchor)
+            lastpiece = pieces
+            while lastpiece.address[1]:
+                lastpiece = lastpiece.address[1]
+            anchor_next = anchor.address[1]
+            lastpiece.address[1] = anchor_next
+            pieces.address[0] = anchor
+            anchor.address[1] = pieces
+            anchor_next.address[0] = lastpiece
+        #
+        s_addr = annmodel.SomeAddress()
+        s_None = annmodel.s_None
+        self.gc_detach_callback_pieces_ptr = getfn(gc_detach_callback_pieces,
+                                                   [], s_addr)
+        self.gc_reattach_callback_pieces_ptr=getfn(gc_reattach_callback_pieces,
+                                                   [s_addr], s_None)
 
     def need_thread_support(self, gctransformer, getfn):
         # Threads supported "out of the box" by the rest of the code.
diff --git a/rpython/memory/gctransform/framework.py 
b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -800,6 +800,21 @@
     def gct_gc_adr_of_root_stack_top(self, hop):
         self._gc_adr_of_gcdata_attr(hop, 'root_stack_top')
 
+    def gct_gc_detach_callback_pieces(self, hop):
+        op = hop.spaceop
+        assert len(op.args) == 0
+        hop.genop("direct_call",
+                  [self.root_walker.gc_detach_callback_pieces_ptr],
+                  resultvar=op.result)
+
+    def gct_gc_reattach_callback_pieces(self, hop):
+        op = hop.spaceop
+        assert len(op.args) == 1
+        hop.genop("direct_call",
+                  [self.root_walker.gc_reattach_callback_pieces_ptr,
+                   op.args[0]],
+                  resultvar=op.result)
+
     def gct_gc_shadowstackref_new(self, hop):
         op = hop.spaceop
         livevars = self.push_roots(hop)
diff --git a/rpython/rlib/_stacklet_asmgcc.py b/rpython/rlib/_stacklet_asmgcc.py
--- a/rpython/rlib/_stacklet_asmgcc.py
+++ b/rpython/rlib/_stacklet_asmgcc.py
@@ -32,6 +32,7 @@
             if not p.handle:
                 return False
             self.context = llmemory.cast_ptr_to_adr(p.handle)
+            self.next_callback_piece = p.callback_pieces
             anchor = p.anchor
             del p
             self.curframe = lltype.malloc(WALKFRAME, flavor='raw')
@@ -50,11 +51,17 @@
             retaddraddr = self.translateptr(retaddraddr)
             curframe.frame_address = retaddraddr.address[0]
 
-        def teardown(self):
-            lltype.free(self.curframe, flavor='raw')
-            lltype.free(self.otherframe, flavor='raw')
-            self.context = llmemory.NULL
-            return llmemory.NULL
+        def fetch_next_stack_piece(self):
+            if self.next_callback_piece == llmemory.NULL:
+                lltype.free(self.curframe, flavor='raw')
+                lltype.free(self.otherframe, flavor='raw')
+                self.context = llmemory.NULL
+                return False
+            else:
+                anchor = self.next_callback_piece
+                self.next_callback_piece = anchor.address[1]  # next
+                self.fill_initial_frame(self.curframe, anchor)
+                return True
 
         def next(self, obj, prev):
             #
@@ -117,7 +124,10 @@
                                                               location)
                 # ^^^ non-translated
                 if caller.frame_address == llmemory.NULL:
-                    return self.teardown()    # completely done with this stack
+                    # completely done with this piece of stack
+                    if not self.fetch_next_stack_piece():
+                        return llmemory.NULL
+                    continue
                 #
                 self.otherframe = callee
                 self.curframe = caller
@@ -154,6 +164,7 @@
 SUSPSTACK = lltype.GcStruct('SuspStack',
                             ('handle', _c.handle),
                             ('anchor', llmemory.Address),
+                            ('callback_pieces', llmemory.Address),
                             rtti=True)
 NULL_SUSPSTACK = lltype.nullptr(SUSPSTACK)
 CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
@@ -197,6 +208,8 @@
     gcrootfinder.suspstack.anchor = stackanchor
     alternateanchor.prev = alternateanchor
     alternateanchor.next = alternateanchor
+    gcrootfinder.suspstack.callback_pieces = (
+        llop.gc_detach_callback_pieces(llmemory.Address))
 
 def _new_runfn(h, _):
     # Here, we are in a fresh new stacklet.
@@ -250,6 +263,7 @@
         # make a fresh new clean SUSPSTACK
         newsuspstack = lltype.malloc(SUSPSTACK)
         newsuspstack.handle = _c.null_handle
+        newsuspstack.callback_pieces = llmemory.NULL
         self.suspstack = newsuspstack
         # Invoke '_new_callback' by closing the stack
         h = pypy_asm_stackwalk2(llhelper(FUNCNOARG_P, _new_callback),
@@ -274,6 +288,10 @@
         #
         # Return from a new() or a switch(): 'h' is a handle, possibly
         # an empty one, that says from where we switched to.
+        if self.suspstack and self.suspstack.callback_pieces:
+            llop.gc_reattach_callback_pieces(lltype.Void,
+                                             self.suspstack.callback_pieces)
+            self.suspstack.callback_pieces = llmemory.NULL
         if not h:
             raise MemoryError
         elif _c.is_empty_handle(h):
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -886,6 +886,11 @@
     def op_gc_stack_bottom(self):
         pass       # marker for trackgcroot.py
 
+    def op_gc_detach_callback_pieces(self):
+        raise NotImplementedError("gc_detach_callback_pieces")
+    def op_gc_reattach_callback_pieces(self):
+        raise NotImplementedError("gc_reattach_callback_pieces")
+
     def op_gc_shadowstackref_new(self):   # stacklet+shadowstack
         raise NotImplementedError("gc_shadowstackref_new")
     def op_gc_shadowstackref_context(self):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -516,6 +516,10 @@
     'gc_asmgcroot_static':  LLOp(sideeffects=False),
     'gc_stack_bottom':      LLOp(canrun=True),
 
+    # for stacklet+asmgcroot support
+    'gc_detach_callback_pieces': LLOp(),
+    'gc_reattach_callback_pieces': LLOp(),
+
     # for stacklet+shadowstack support
     'gc_shadowstackref_new':      LLOp(canmallocgc=True),
     'gc_shadowstackref_context':  LLOp(),
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to